Leetcode刷题——广度优先搜索与深度优先搜索题目(一)

260 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

广度优先搜索

1020. 飞地的数量

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。

一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

示例 1: 在这里插入图片描述

输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] 输出:3 解释:有三个 1 被 0包围。一个 1 没有被包围,因为它在边界上。

示例 2: 在这里插入图片描述

输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] 输出:0 解释:所有 1 都在边界上或可以到达边界。

提示:

m == grid.length n == grid[i].length 1 <= m, n <= 500 grid[i][j] 的值为 0或 1

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/nu…

代码

从边界开始广度优先即可

class Solution {
public:
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int numEnclaves(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        queue<pair<int,int>> q;
        //cout<<m<<" "<<n<<endl;
        for(int i=0; i < m; i++){
            if(grid[i][0]){
                grid[i][0] = 0;
                q.push(make_pair(i, 0));
                
            }
            if(grid[i][n-1]){
                grid[i][n-1] = 0;
                q.push(make_pair(i, n-1));
                
            }
        }

        for(int i=0; i < n; i++){
            if(grid[0][i]){
                grid[0][i] = 0;
                q.push(make_pair(0, i));
            
            }
            if(grid[m-1][i]){
                grid[m-1][i] = 0;
                q.push(make_pair(m-1, i));
                
            }
        }
        
        while(!q.empty()){
            auto [x, y] = q.front();
            q.pop();
            for(int i=0; i < 4; i++){
                int tx, ty;
                tx = x + dx[i];
                ty = y + dy[i];
                if(tx >= 0 && tx < m && ty >= 0 && ty < n){
                    //cout<<x<<" "<<y<<" "<<tx<<" "<<ty<<endl;
                    if(grid[tx][ty]){
                        grid[tx][ty]= 0;
                    q.push(make_pair(tx, ty));
                    }
                    
                }
            }
        }
        int ans=0;
        for(int i=0; i < m; i++){
            for(int j=0; j < n; j++){
                if(grid[i][j]){
                    ans++;
                }
            }
        }
        return ans;
    }
};

1345. 跳跃游戏 IV

题目

给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。

每一步,你可以从下标 i 跳到下标:

i + 1 满足:i + 1 < arr.length i - 1 满足:i - 1 >= 0 j 满足:arr[i] == arr[j] 且 i != j 请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。

注意:任何时候你都不能跳到数组外面。

示例 1:

输入:arr = [100,-23,-23,404,100,23,23,23,3,404] 输出:3 解释:那你需要跳跃 3 次,下标依次为 0 --> 4 --> 3 --> 9 。下标 9 为数组的最后一个元素的下标。 示例 2:

输入:arr = [7] 输出:0 解释:一开始就在最后一个元素处,所以你不需要跳跃。 示例 3:

输入:arr = [7,6,9,6,9,6,9,7] 输出:1 解释:你可以直接从下标 0 处跳到下标 7 处,也就是数组的最后一个元素处。 示例 4:

输入:arr = [6,1,9] 输出:2 示例 5:

输入:arr = [11,22,7,7,7,7,7,7,7,22,13] 输出:3

提示:

1 <= arr.length <= 5 * 10^4 -10^8 <= arr[i] <= 10^8

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ju…

分析

从题目可以看出这道题可以使用广度优先搜索解决,需要的步数就是遍历到结尾时的层数。但是这里的问题在于超时,因为直接暴力的搜索会有重复的结点访问,这一部分是可以通过剪枝优化。

因为通过暴力搜索的完整图从理论上有可能是无穷的,所以在这里为了理解方便只画图中部分的情况

如下图所示 在这里插入图片描述 为了解决这个问题我们可以对结点做标记,如果已经访问过则不在访问,代码中的set<int> sm.erase的目的都是为了移除掉已访问的结点以进行剪枝,从而优化时间

代码

struct Node{
    int idx;
    int level;
};

class Solution {
public:
    int minJumps(vector<int>& arr) {
        map<int, vector<int>> m;
        set<int> s;
        queue<Node> q;
        for(int i=0; i < arr.size(); i++){
            m[arr[i]].push_back(i);
        }
        Node n;
        n.idx = 0;
        n.level = 0;
        q.push(n);
        while(!q.empty()){
            Node p=q.front();

            q.pop();
            if(p.idx == arr.size()-1){
                return p.level;
            }
            s.insert(p.idx);
            if(m.count(arr[p.idx])){
                for(int i=0; i < m[arr[p.idx]].size(); i++){
                    if(!s.count(m[arr[p.idx]][i])){
                        Node tmp;
                        tmp.idx = m[arr[p.idx]][i];
                        tmp.level = p.level + 1;
                        q.push(tmp);
                    }
                }
                m.erase(arr[p.idx]);
            }
            
            if(p.idx > 0 && !s.count(p.idx-1)){
                Node tmp;
                tmp.idx = p.idx - 1;
                tmp.level = p.level + 1;
                q.push(tmp);
            }
            if(p.idx <= arr.size()-1 && !s.count(p.idx+1)){
                Node tmp;
                tmp.idx = p.idx + 1;
                tmp.level = p.level + 1;
                q.push(tmp);
            }
        }
        return -1;
    }
};