在寻路这类题目时,对每一个位置的节点出发去遍历,很容易超时,需要想到是否重复搜素了,如何减少不必要的搜索
https://leetcode.com/problems/longest-increasing-path-in-a-matrix/
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:
nums = [
[9,9,4],
[6,6,8],
[2,1,1]
]
Return 4
The longest increasing path is [1, 2, 6, 9].
Example 2:
nums = [
[3,4,5],
[3,2,6],
[2,2,1]
]
Return 4
The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.
需要理解 每个位置只需要遍历一次就够了,所以需要设置一个vis访问标识 ,避免重复的访问
ac代码如下
class Solution {
public:
int m, n;
int dfs(vector<vector<int>>& matrix, int x, int y, vector<vector<int>> &ansCeng)
{
int dir[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, {0,-1} };
int cnt = 0;
for (int i = 0; i < 4; i++)
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if (!(nx >= 0 && nx < m && ny >= 0 && ny < n))
continue;
if (matrix[nx][ny] <= matrix[x][y])
continue;
cnt++;
if (ansCeng[nx][ny] == -1)
{
ansCeng[x][y] = max(ansCeng[x][y], 1 + dfs(matrix, nx, ny, ansCeng)); // dfs不需要回溯
}
else{
ansCeng[x][y] = max(ansCeng[x][y], 1 + ansCeng[nx][ny]);
}
}
if (cnt == 0)
ansCeng[x][y] = 1;
return ansCeng[x][y];
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
m = matrix.size();
if (m == 0)
return 0;
n = matrix[0].size();
if (n == 0)
return 0;
vector<vector<int>> ansCeng = vector<vector<int>>(m, vector<int>(n, -1));
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (ansCeng[i][j] == -1)
dfs(matrix, i, j, ansCeng);
}
}
int maxH = 1;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (ansCeng[i][j] > maxH)
maxH = ansCeng[i][j];
}
}
return maxH;
}
};
测试
void test1()
{
int a[3][3] = {{9,9,4},{6,6,8},{2,1,1}};
vector<vector<int>> v(3, vector<int>(3,-1));
for(int i=0;i<3;i++)
{
for(int j =0;j<3;j++)
{
v[i][j] = a[i][j];
}
}
Solution sol;
cout << sol.longestIncreasingPath(v) << endl;
}
void test2()
{
int a[3][3] = {{3,4,5},{3,2,6},{2,2,1}};
vector<vector<int>> v(3, vector<int>(3,-1));
for(int i=0;i<3;i++)
{
for(int j =0;j<3;j++)
{
v[i][j] = a[i][j];
}
}
Solution sol;
cout << sol.longestIncreasingPath(v) << endl;
}
https://leetcode.com/problems/pacific-atlantic-water-flow/
Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the “Pacific ocean” touches the left and top edges of the matrix and the “Atlantic ocean” touches the right and bottom edges.
Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.
Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.
Note:
The order of returned grid coordinates does not matter.
Both m and n are less than 150.
Example:
Given the following 5x5 matrix:
Pacific ~ ~ ~ ~ ~
~ 1 2 2 3 (5) *
~ 3 2 3 (4) (4) *
~ 2 4 (5) 3 1 *
~ (6) (7) 1 4 5 *
~ (5) 1 1 2 4 *
* * * * * Atlantic
Return:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
此题用dfs深度太大,直接超时。
采用bfs,每个点都作为出发点遍历,可以ac,不过耗时太多,因为有很多多于的遍历
从边缘出发,这样一遍后可以确定一些点(确定的是可以到达的点,这些点后面就不需要再进行遍历了)。
class Solution {
public:
int m, n;
vectorint , int>> ans;
// bfs,队列
void flow(vector<vector<int>>& matrix, int i, int j, vector<vector<bool>> &pv)
{
vector<bool> vis = vector<bool>(m*n, false);
queue<int> que;
que.push(i*n + j);
vis[i*n + j] = true;
while (!que.empty())
{
int x = que.front() / n;
int y = que.front() % n;
que.pop();
int dir[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
for (int k = 0; k < 4; k++)
{
int nx = x + dir[k][0];
int ny = y + dir[k][1];
if (!(nx >= 0 && nx < m && ny >= 0 && ny < n))
continue;
// 高度比当前高度小的,或者已经是true,不需要访问了
if (vis[nx*n + ny] || matrix[nx][ny] < matrix[x][y] || pv[nx][ny] == true)
continue;
pv[nx][ny] = true;
vis[nx*n + ny] = true;
que.push(nx*n + ny);
}
}// end while
}
vectorint , int>> pacificAtlantic(vector<vector<int>>& matrix) {
m = matrix.size();
if (m == 0)
return ans;
n = matrix[0].size();
if (n == 0)
return ans;
vector<vector<bool>> Pacific;
vector<vector<bool>> Atlantic;
Pacific.resize(m, vector<bool>(n, false));
Atlantic.resize(m, vector<bool>(n, false));
for (int i = 0; i < m; i++){
Pacific[i][0] = true;
Atlantic[i][n - 1] = true;
}
for (int j = 0; j < n; j++)
{
Pacific[0][j] = true;
Atlantic[m - 1][j] = true;
}
// bfs求解
for (int i = 0; i < m; i++)
{
flow(matrix, i, 0, Pacific);
flow(matrix, i, n - 1, Atlantic);
}
for (int j = 0; j < n; j++)
{
flow(matrix, 0, j, Pacific);
flow(matrix, m-1, j, Atlantic);
}
// 存储结果
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (Pacific[i][j] && Atlantic[i][j])
{
ans.push_back(pair<int, int>{i, j});
}
}
}
return ans;
}
};