一、题目描述
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).
Example 1:
Input: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
Output: 4
Explanation: The longest increasing path is [1, 2, 6, 9].
Example 2:
Input: nums =
[
[3,4,5],
[3,2,6],
[2,2,1]
]
Output: 4
Explanation: The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.
二、题目分析
根据题意,我们需要在给定的矩阵中找出一个最长的递增序列,返回其长度。
在这里我们可以将给定的矩阵近似看成有向图,当且仅当图的每个顶点(数字)的周围(上下左右四个方向)的顶点的数字大于该顶点时,才有从该顶点指向另一顶点的边。
- e.g. 题目的Example2 中给出的矩阵形成的图如下:
将矩阵看作图后,我们就可以将问题转换成求图的最长路径的长度,自然我们使用DFS来找这样的一条路径,即以图的每一个顶点作为DFS的起点,在搜索时使用二维数组记录从每个顶点出发的最长路径长度(若该点出度为0,则其最长路径长度为1)。这里将二维数组初始化为0,就可以通过判断数组某个位置是否等于0作为对应的顶点是否访问过的依据,减少搜索次数。我们在遍历图时,记录下最大值,在最后返回。
三、具体实现
通过上面分析,可知算法复杂度为 O ( n 2 ) O(n^2) O(n2)。实现如下:
class Solution {
public:
int longestIncreasingPath( vector<vector<int>> &matrix ) {
width = matrix.size();
if ( width == 0 )
return 0;
len = matrix.at( 0 ).size();
int **res = new int*[width];
for ( int i = 0; i < width; ++i )
res[i] = new int[len]();
int pathLen = 0;
for ( int i = 0; i < width; ++i ) {
for ( int j = 0; j < len; ++j ) {
if ( res[i][j] == 0 )
pathLen = max( pathLen, DFS( matrix, i, j, res ) );
}
}
for ( int i = 0; i < width; ++i )
delete [] res[i];
delete [] res;
return pathLen;
}
private:
const pair<int, int> direction[4]
= { make_pair( -1, 0 ), make_pair( 1, 0 ), make_pair( 0, -1 ), make_pair( 0, 1 ) };
int width;
int len;
int DFS( vector<vector<int>> &matrix, int _x, int _y, int **res ) {
bool maxima = true; // to check whether matrix[_x][_y] is maxima
for ( int i = 0; i < 4; ++i ) { // 4 directions
int x = _x + direction[i].first, y = _y + direction[i].second;
if ( x < 0 || y < 0 || x >= width || y >= len || matrix[x][y] <= matrix[_x][_y] )
continue;
maxima = false;
if ( res[x][y] != 0 )
res[_x][_y] = max( 1 + res[x][y], res[_x][_y] );
else
res[_x][_y] = max( 1 + DFS( matrix, x, y, res ), res[_x][_y] );
}
if ( maxima )
res[_x][_y] = 1;
return res[_x][_y];
}
};