【搜索】B075_LC_太平洋大西洋水流问题(暴搜 / 反向思维)

一、Problem

给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。

规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。

请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标

给定下面的 5x5 矩阵:

  太平洋 ~   ~   ~   ~   ~ 
       ~  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  *
          *   *   *   *   * 大西洋

返回:

[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上图中带括号的单元).

提示:

输出坐标的顺序不重要
m 和 n 都小于150

二、Solution

方法一:暴搜(超时)

107 / 113 …

const int N=155;
class Solution {
     
public:
	int n, m, f1, f2, d[4][2] = {
      {
     1,0},{
     0,-1},{
     0,1},{
     -1,0} };
    unordered_map<int, unordered_map<int, bool>> vis;
	bool meetA(int x, int y) {
     return x<0 || y<0;}
	bool meetB(int x, int y) {
     return x>=n || y>=m;}
	
	void dfs(int x, int y, vector<vector<int>>& g) {
     
		for (int k=0; k<4; k++) {
     
			int xx=x+d[k][0], yy=y+d[k][1];
			if (meetA(xx, yy)) f1=true;
			if (meetB(xx, yy)) f2=true;
    		if (f1 && f2) return;
			if (xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && g[xx][yy] <= g[x][y]) {
     
				vis[xx][yy]=true;
				dfs(xx, yy, g);
			}
		}
	}
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& g) {
     
        if (g.empty()) return {
     };
    	n=g.size(), m=g[0].size();
        vector<vector<int>> ans;
    	for (int i=0; i<n; i++)
    	for (int j=0; j<m; j++) {
     
            vis.clear();
            vis[i][j] = true;
    		dfs(i, j, g);
    		if (f1 && f2)
				ans.push_back({
     i, j});
            f1=false, f2=false;
    	}
    	return ans;
    }
};

加入了记忆化,提前返回,为什么还是会超时…


const int N=155;
class Solution {
     
public:
	int n, m, f1, f2, d[4][2] = {
      {
     1,0},{
     0,-1},{
     0,1},{
     -1,0} };
    unordered_map<int, unordered_map<int, bool>> vis, m1, m2;
	bool meetA(int x, int y) {
     return x<0 || y<0;}
	bool meetB(int x, int y) {
     return x>=n || y>=m;}
	
	void dfs(int x, int y, vector<vector<int>>& g) {
     
        if (m1[x][y] && m2[x][y]) {
     
            f1=true, f2=true;
            return;
        }
		for (int k=0; k<4; k++) {
     
			int xx=x+d[k][0], yy=y+d[k][1];
			if (meetA(xx, yy)) f1=true;
			if (meetB(xx, yy)) f2=true;
    		if (f1 && f2)      return;
			if (xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && g[xx][yy] <= g[x][y]) {
     
				vis[xx][yy]=true;
				dfs(xx, yy, g);
			}
		}
	}
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& g) {
     
        if (g.empty()) return {
     };
    	n=g.size(), m=g[0].size();
        vector<vector<int>> ans;
    	for (int i=0; i<n; i++)
    	for (int j=0; j<m; j++) {
     
            vis.clear();
            vis[i][j] = true;
    		dfs(i, j, g);
    		if (f1 && f2) {
     
    			m1[i][j]=true, m2[i][j]=true;
				ans.push_back({
     i, j});
    		}
            f1=false, f2=false;
    	}
    	return ans;
    }
};

复杂度分析

  • 时间复杂度: O ( n 2 × Q ) O(n^2 × Q) O(n2×Q)
  • 空间复杂度: O ( ) O() O()

方法二:反向思维

思路

直接从大洋出发,途中能经过的点就是答案…

正向做妥妥的 O ( n 2 × Q ) O(n^2 × Q) O(n2×Q);反向做的话,途中会过滤掉很多已经遍历过的结点,所以会很快…

class Solution {
     
public:
	int n, m, d[4][2] = {
      {
     1,0},{
     0,-1},{
     0,1},{
     -1,0} };
	void dfs(int x, int y, vector<vector<int>>& vis, vector<vector<int>>& g) {
     
		vis[x][y]=true;
		for (int k=0; k<4; k++) {
     
			int xx=x+d[k][0], yy=y+d[k][1];
			if (xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && g[xx][yy] >= g[x][y])
				dfs(xx, yy, vis, g);
		}
	}
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& g) {
     
        if (g.empty()) return {
     };
    	n=g.size(), m=g[0].size();
        vector<vector<int>> ans, vis1(n, vector<int>(m, 0)), vis2(n, vector<int>(m, 0));
    	for (int i=0; i<n; i++) {
     
    		dfs(i, 0, vis1, g);
    		dfs(i, m-1, vis2, g);
    	}
    	for (int j=0; j<m; j++) {
     
    		dfs(0, j, vis1, g);
    		dfs(n-1, j, vis2, g);
    	}
    	for (int i=0; i<n; i++) 
    	for (int j=0; j<m; j++) if (vis1[i][j] && vis2[i][j])
    		ans.push_back({
     i, j});
    	return ans;
    }
};

复杂度分析

  • 时间复杂度: O ( n m ) O(nm) O(nm)
  • 空间复杂度: O ( n m ) O(nm) O(nm)

你可能感兴趣的:(dfs,bfs)