代码编织梦想

解题方法一:深度优先搜索

我们可以将二维网格看成一个无向图,竖直或水平相邻的 1 之间有边相连。

为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则以其为起始节点开始进行深度优先搜索。在深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。

最终岛屿的数量就是我们进行深度优先搜索的次数。

//深度优先搜索
class Solution {
private:
    void dfs(vector<vector<char>>& grid,int r,int c){
        int nr = grid.size();
        int nc = grid[0].size();

        grid[r][c] = '0';
        if(r-1 >= 0 && grid[r-1][c]=='1') dfs(grid,r-1,c);
        if(r+1 < nr && grid[r+1][c]=='1') dfs(grid,r+1,c);
        if(c-1 >= 0 && grid[r][c-1]=='1') dfs(grid,r,c-1);
        if(c+1 < nc && grid[r][c+1]=='1') dfs(grid,r,c+1);
    }
public:
    int numIslands(vector<vector<char>>& grid) {
        int nr = grid.size();
        if(!nr) return 0;
        int nc = grid[0].size();
    
        int num_islands = 0;
        for (int r=0;r<nr;r++){
            for(int c=0;c<nc;c++){
                if(grid[r][c] == '1'){
                    ++num_islands;
                    dfs(grid,r,c);
                }
            }
        }
        return num_islands;
    }
};

解题方法二:广度优先搜索

同样地,我们也可以使用广度优先搜索代替深度优先搜索。

为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则将其加入队列,开始进行广度优先搜索。在广度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。直到队列为空,搜索结束。

//广度优先搜索 队列
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int nr = grid.size();
        if(!nr) return 0;
        int nc = grid[0].size();

        int num_islands = 0;
        for(int r=0;r<nr;++r){
            for(int c=0;c<nc;++c){
                if(grid[r][c]=='1'){
                    ++num_islands;
                    grid[r][c]='0';
                    queue<pair<int,int>> neighbors;
                    neighbors.push({r,c});
                    while(!neighbors.empty()){
                        auto rc=neighbors.front();
                        neighbors.pop();
                        int row = rc.first,col=rc.second;
                        if(row-1>=0 && grid[row-1][col]=='1'){
                            neighbors.push({row-1,col});
                            grid[row-1][col] = '0';
                        }
                        if(row+1<nr && grid[row+1][col]=='1'){
                            neighbors.push({row+1,col});
                            grid[row+1][col] = '0';
                        }
                        if(col-1>=0 && grid[row][col-1]=='1'){
                            neighbors.push({row,col-1});
                            grid[row][col-1] = '0';
                        }
                        if(col+1<nc && grid[row][col+1]=='1'){
                            neighbors.push({row,col+1});
                            grid[row][col+1] = '0';
                        }
                    }
                }
            }
        }
        return num_islands;
    }
};

方法一:位移

算法

如上述所说,算法由两个步骤组成:

我们通过右移,将两个数字压缩为它们的公共前缀。在迭代过程中,我们计算执行的右移操作数。
将得到的公共前缀左移相同的操作数得到结果。

//位移
class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        int shift = 0;
        // 找到公共前缀
        while (m < n) {
            m >>= 1;
            n >>= 1;
            ++shift;
        }
        return m << shift;
    }
};

方法二:Brian Kernighan算法

//Brian Kernighan算法
class Solution{
public:
    int rangeBitwiseAnd(int m,int n){
        while(m<n){
            n = n & (n-1);
        }
        return n;
    }
};

 Brian Kernighan算法的衍生题目:

 方法一:移位实现位计数(造轮子)

//位移
class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        int shift = 0;
        // 找到公共前缀
        while (m < n) {
            m >>= 1;
            n >>= 1;
            ++shift;
        }
        return m << shift;
    }
};

方法二:Brian Kernighan算法

还有一个位移相关的算法叫做「Brian Kernighan 算法」,它用于清除二进制串中最右边的 1。

Brian Kernighan 算法的关键在于我们每次对 number 和 number−1 之间进行按位与运算后,number 中最右边的 1 会被抹去变成 0。

//Brian Kernighan算法
class Solution{
public:
    int rangeBitwiseAnd(int m,int n){
        while(m<n){
            n = n & (n-1);
        }
        return n;
    }
};

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_73682715/article/details/141198815

leetcode刷题——day1_哈哈哈哈士奇vip的博客-爱代码爱编程

一边看算法,一边刷题吧,先从简单的开始: 刷题之路这就开始了? 561. Array Partition I Given an array of 2n integers, your task is to group t

LeetCode刷题Day10-爱代码爱编程

一:方法总结 二:题目 79.单词搜索 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 思路:先遍历board,找到一个能匹配的字符,确定入口,同时创建新的 vis 数组保存已经走过的路径。 public boolean exist(char[

Leetcode刷题Day9(C#)-爱代码爱编程

190. 颠倒二进制位 题目描述: 颠倒给定的 32 位无符号整数的二进制位。 提示: 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。 在 Java 中,编译器使用二进制补码记法来表示有符号整数

代码随想录leetcode刷题day01-二分查找-爱代码爱编程

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target , 写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 class Solution { public int search(int[] nums, int target) { //如果明显不存在,则先判断,避免不必

leetcode刷题day5-爱代码爱编程

leetcode刷题Day5 38.Excel表列序号 给你一个字符串 columnTitle ,表示 Excel 表格中的列名称。返回该列名称对应的列序号 。 示例:输入: columnTitle = “A”; 输出:

【hot100】leetcode—64. 最小路径和-爱代码爱编程

目录 1- 思路题目识别动规五部曲 2- 实现⭐64. 最小路径和——题解思路 3- ACM 实现 原题链接:64. 最小路径和 1- 思路 题目识别 识别1 :给一个二维数

python世界:力扣29题两数相除算法实践-爱代码爱编程

Python世界:力扣29题两数相除算法实践[ 任务背景实现思路模拟思路编码实现 本文小结 任务背景 本问题来自于力扣29题,在做完大数相乘后,顺带也看下两数相除。 给定两个整

【javascript】leetcode:707设计链表-爱代码爱编程

文章目录 题目内容题目分析(1) 获取第n个节点的值(2) 头部插入节点(3) 尾部插入节点(4) 第n个节点前插入节点(5) 删除第n个节点 完整代码 题目内容 题目分析 添加哨兵节点

leetcode面试经典150题-爱代码爱编程

看本文之前,强烈建议大家看一下我的另一篇文章,那个文章也是面试经典150题之一: Leetcode面试经典150题-114.二叉树展开为链表-CSDN博客 实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器: BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个

【每日一题】leetcode 2332.坐上公交的最晚时间(数组、双指针、二分查找、排序)-爱代码爱编程

【每日一题】LeetCode 2332.坐上公交的最晚时间(数组、双指针、二分查找、排序) 题目描述 给你一个下标从 0 开始长度为 n 的整数数组 buses ,其中 buses[i] 表示第 i 辆公交车的出发时间。

c++速通leetcode中等第3题-爱代码爱编程

双指针法:两个指针分别指向左右边界,记录最大面积,由于面积由短板决定,两个指针中较短的短指针向内移动一格,再次记录最大面积, 直到两指针相遇,得出答案。 class Solution { public: int maxArea(vector<int>& height) { int i = 0, j = he

leetcode 470. 用 rand7() 实现 rand10()-爱代码爱编程

Leetcode 470. 用 Rand7() 实现 Rand10() 已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。 不要使用系统的

【leetcode】堆习题-爱代码爱编程

215.数组中的第K个最大元素 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n

leetcode 算法笔记-爱代码爱编程

1.枚举 采用枚举算法解题的一般思路如下: 确定枚举对象、枚举范围和判断条件,并判断条件设立的正确性。一一枚举可能的情况,并验证是否是问题的解。考虑提高枚举算法的效率。 我们可以从下面几个方面考虑提高算法的效率: 抓住问题状态的本质,尽可能缩小问题状态空间的大小。加强约束条件,缩小枚举范围。根据某些问题特有的性质,例如对称性等,避免对本质相同的状态

leetcode 刷题 day03-爱代码爱编程

因为很久没有刷过题了,打算这段时间把每种类型的过一遍熟悉一下——好了下面进入刷题模式(学习模式) 继续上次的会议室练习,这次我们换用贪心算法——扫描线来解决问题 leetcode上扫描线的概念如下所示:  该题用到的是扫描线技巧。(学习howard大佬的思想,其原文链接在这:. - 力扣(LeetCode)) 本题题意求的是会议冲突数量的最