如果把矩阵元素看做点,小的元素到打的元素看做边连起来,这道题等价于在一个有向图中寻找最长路径。
第一想法是用dfs或bfs,但是直接做超时了。以dfs为例,时间复杂度为O(2^(m+n)),空间复杂度O(h)=O(mn)
由于dfs中很多节点的最长路径都被重复计算了,因此可以 Memorization 将结果保存下来。
方法一:DFS+Memorization
每条边和每个节点都只访问了一次,O(V+E),O(V)=O(mn),O(E)=O(4V)=O(mn),所以时间复杂度O(mn)
空间复杂度O(mn)
class Solution { public: vector<vector<int>> dirs={{0,1},{0,-1},{1,0},{-1,0}}; int longestIncreasingPath(vector<vector<int>>& matrix) { int m=matrix.size(), n=m==0?0:matrix[0].size(); vector<vector<int>> cache(m,vector<int>(n,0)); int res=0; for (int i=0;i<m;++i){ for (int j=0;j<n;++j){ res = max(res, dfs(matrix,i,j,cache)); } } return res; } int dfs(vector<vector<int>> &matrix, int i, int j, vector<vector<int>> &cache){ if (cache[i][j]!=0) return cache[i][j]; int max_len=1; for (auto dir:dirs){ int x=i+dir[0], y=j+dir[1]; if (x>=0 && x<matrix.size() && y>=0 && y<matrix[0].size() && matrix[x][y]>matrix[i][j]){ max_len = max(max_len, 1+dfs(matrix,x,y,cache)); } } cache[i][j] = max_len; return max_len; } };
方法二:Topological Sort
由于这道题四个方向都可以,如果用dp来做是很麻烦的,dp[i]依赖的四个方向的dp值不一定是已经求得的。所以要用DP来做的话,需要用拓扑的顺序来依次更新dp。
由于这道题比较简单,也不需要dp了,直接用拓扑排序来做。用入度做和出度做本题没区别。
class Solution { public: vector<vector<int>> dirs={{0,1},{0,-1},{1,0},{-1,0}}; int longestIncreasingPath(vector<vector<int>>& matrix) { int m=matrix.size(), n=m==0?0:matrix[0].size(); vector<vector<int>> indegree(m,vector<int>(n,0)); // calculate indegree for (int i=0;i<m;++i){ for (int j=0;j<n;++j){ for (auto dir:dirs){ int x=i+dir[0], y=j+dir[1]; if (x>=0 && x<m && y>=0 && y<n){ if (matrix[x][y]<matrix[i][j]) ++indegree[i][j]; } } } } for (int i=0;i<m;++i){ for (int j=0;j<n;++j){ cout << indegree[i][j] << ' '; } cout << endl; } queue<pair<int,int>> q; for (int i=0;i<m;++i){ for (int j=0;j<n;++j){ if (indegree[i][j]==0) q.push({i,j}); } } int len=0; while (!q.empty()){ ++len; //cout << "size:" << q.size() << endl; int k=q.size(); for (int cnt=0;cnt<k;++cnt){ auto tmp=q.front(); q.pop(); int i=tmp.first, j=tmp.second; for (auto dir:dirs){ int x=i+dir[0], y=j+dir[1]; if (x>=0 && x<m && y>=0 && y<n){ if (matrix[x][y]>matrix[i][j]){ --indegree[x][y]; if (indegree[x][y]==0){ q.push({x,y}); //cout << x << ' ' << y << endl; } } } } } } return len; } };