问题描述

Given an integer matrix, find the length of the longest increasing path. From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).

想法与实现

这道题一开始看到就直接想用深度优先搜索来实现,没什么想不出的地方。

class Solution {
private:
    int max;
    vector<vector<bool>> flag;
    int sizeX;
    int sizeY;
    
    bool isValid(int i, int j) {
        if (i >= 0 && i < sizeX && j >= 0 && j < sizeY) {
            return true;
        } else {
            return false;
        }
    }
    
    void dfs(vector<vector<int>>& matrix, int posX, int posY, int sum) {
        if (flag[posX][posY] == true) {
            flag[posX][posY] = false;
            sum++;
            vector<vector<int>> dirs = {
            	{-1, 0}, 
            	{1, 0}, 
            	{0, -1}, 
            	{0, 1}
            };
            int sz = dirs.size();
            for (int i = 0; i < sz; i++) {
                int newPosX = posX + dirs[i][0];
                int newPosY = posY + dirs[i][1];
                if (isValid(newPosX, newPosY) && flag[newPosX][newPosY] == true && 
                    matrix[posX][posY] < matrix[newPosX][newPosY]) {
                    
                    dfs(matrix, newPosX, newPosY, sum);     
                }
            }
            if (sum > max) {
                max = sum;
            }
            flag[posX][posY] = true;
            return;
        }
    }
    
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        max = 0;
        sizeX = matrix.size();
        sizeY = matrix[0].size();
        flag = vector<vector<bool>>(sizeX, vector<bool>(sizeY, true));
        for (int i = 0; i < sizeX; i++) {
            for (int j = 0; j < sizeY; j++) {
                dfs(matrix, i, j, 0);
            }
        }
        return max;
    }
};

但是在写完后会发现,这样写是超时的。这时候就要基于观察,来优化一下。在深度优先搜索中,做了很多无用功,对于每个点,都会执行很多次dfs函数,因此可以Memo的方式,来缓存每次执行的结果,由此就不需要多次计算。

class Solution {
private:
    int max;
    vector<vector<int>> flag;
    int sizeX;
    int sizeY;
    
    bool isValid(int i, int j) {
        if (i >= 0 && i < sizeX && j >= 0 && j < sizeY) {
            return true;
        } else {
            return false;
        }
    }
    
    int getMax(int a, int b) {
        if (a > b) {
            return a;
        } else {
            return b;
        }
    }
    
    int dfs(vector<vector<int>>& matrix, int posX, int posY) {
        if (flag[posX][posY] == 0) {
            int sum = 0;
            vector<vector<int>> dirs = {
            	{-1, 0}, 
            	{1, 0}, 
            	{0, -1}, 
            	{0, 1}
            };
            int sz = dirs.size();
            for (int i = 0; i < sz; i++) {
                int newPosX = posX + dirs[i][0];
                int newPosY = posY + dirs[i][1];
                if (isValid(newPosX, newPosY) && 
                    matrix[posX][posY] < matrix[newPosX][newPosY]) {
                    
                    sum = getMax(dfs(matrix, newPosX, newPosY), sum);
                }
            }
            
            flag[posX][posY] = sum + 1;
            return sum + 1;
        } else {
            return flag[posX][posY];
        }
    }
    
public:
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        max = 0;
        sizeX = matrix.size();
        if (sizeX == 0) {
            return max;
        }
        sizeY = matrix[0].size();
        if (sizeY == 0) {
            return max;
        }
        flag = vector<vector<int>>(sizeX, vector<int>(sizeY, 0));
        for (int i = 0; i < sizeX; i++) {
            for (int j = 0; j < sizeY; j++) {
                max = getMax(max, dfs(matrix, i, j));
            }
        }
        return max;
    }
};

评论