每日两道力扣,day3

每日两道力扣,day3

每日两道力扣,day3

每日两道力扣,今日是:

LCR 173. 点名 - 力扣(LeetCode)

33. 搜索旋转排序数组 - 力扣(LeetCode)

第一题:点名

LCR 173. 点名 - 力扣(LeetCode)

1.思路:

这个题其实有两个方法。一是暴力遍历,二是二分查找。

方法一:

1.遍历找第一个不匹配的位置 < == >if (recordsi != i)

return i;

2.全部匹配,缺席的就是最后一个学号 n < == > return n;

方法二:

利用二分查找的逼近特性,查找不匹配的位置

2.代码实现:

方法一(暴力):

复制代码
class Solution {
public:
    int takeAttendance(vector<int>& records) {
        int n = records.size();
        // 遍历找第一个不匹配的位置
        for (int i = 0; i < n; ++i) {
            if (records[i] != i) {
                return i;
            }
        }
        // 全部匹配,缺席的就是最后一个学号 n
        return n;
    }
};

方法二(二分查找):

复制代码
class Solution {
public:
    int takeAttendance(vector<int>& nums) {
        
        int left = 0, right = nums.size() - 1;
        while(left < right){
            int mid = (left + right)/2;
            if(nums[mid] != mid) right = mid;
            else left = mid + 1;
        }
        if(nums[right] == right) right++;//特殊情况
        return right;
    }
};
3.细节

(1)对于方法一,我们必须考虑前面全部匹配时,最后一个缺席的人就是n这种情况,不然测试用例跑不满。

(2)对于方法二,同理我们必须考虑方法一中的情况,不然同样跑不满。

(3)一定要考虑周全。我最开始直接用二分查找,就因为漏了这个情况卡了好几分钟。然后把我逼急了,我又想出了暴力求解,后面在脑子里面写伪代码的时候,可算整出来了。然后就有了两种解法。

第二题:搜索旋转排序数组

33. 搜索旋转排序数组 - 力扣(LeetCode)


1.思路:

还记得咱们昨天写的寻找旋转排序数组中的最小值吗?那道题用的二分查找,这道题是昨天那道题的一个子题,所以咱们果断采用二分查找。

草图如下:

核心思路:

首先咱们回味一下昨天那道题的思路。题目要求是求寻旋转排序数组中的最小值。

想象一下你在爬坡。将 mid 与右边界 right 进行比较

(1)如果numsmid > numsright,mid 在左侧的高斜坡,最小值肯定在右边,left = mid + 1。让mid往右走一点

(2)反之numsmid < numsright,mid 在右侧的低斜坡,最小值在 mid 或者是 mid 的左边,right = mid。让mid往左走一点。

(3)循环结束时,left 和 right 相遇,指向的就是最小值

同理咱们这个题的大致方向如上,但有一些细节得处理好。

(1)我们并不知道numsmid具体在左侧上坡,还是在右侧上坡。而且咱们也不知道target具体在左侧上坡,还是在右侧上坡。我们必须运用假设法。

(2)首先假设numsmid位于左侧上坡 <=> if(numsleft <= numsmid),其次咱们继续假设target在左侧的半个上坡,即if(target >= numsleft && target < numsmid)

(3)反之,咱们继续假设在右上坡的情况。

2.代码实现:
复制代码
class Solution {
public:
    int search(vector<int>& nums, int target) {
        
        int left = 0, right = nums.size() - 1;
        while(left <= right)
        {
            int mid = left + (right - left)/2;

            // 运气好,第一次就找到了 (注意:返回下标 mid,千万别加 1)
            if(nums[mid] == target)
                return mid;

            // 左边是完美升序的斜坡
            if(nums[left] <= nums[mid])
            {
                // 假设 target 在这半个完美的左坡上
                if(target >= nums[left] && target < nums[mid])
                {
                    // 砍掉右边,在左边找
                    right = mid - 1;
                }
                else
                {
                    // 不在左坡,那一定在右边。砍掉左边!
                    // (注意:这里千万别写 left = mid,会死循环)
                    left = mid + 1;
                }
            }
            // 右边是完美升序的斜坡
            else
            {
                // 假设 target 在这半个完美的右坡上
                // (注意:在升序坡上,target 必须大于 nums[mid])
                if(target > nums[mid] && target <= nums[right])
                {
                    // 砍掉左边,在右边找
                    left = mid + 1;
                }
                else
                {
                    // 不在右坡,那一定在左边。砍掉右边!
                    right = mid - 1;
                }
            }
        }
        
        // 循环都跑完了还没 return,说明真没有
        return -1;
    }
};
3.细节:

我们得采用 int mid = left + (right - left)/2; 来防止数据溢出

好了,今天的每日两道力扣到这里就算是结束了,看完是不是感觉有所收获呢?如果学有所获的话,麻烦给个三连支持一下呗。感谢观看,您的支持,将是我前进路上的重要动力。

相关推荐
小雨下雨的雨8 小时前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.11 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
一条小锦吕*11 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
如竟没有火炬13 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
8Qi813 小时前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
绿算技术14 小时前
万卡推理集群存储选型分析:从核心架构到应用视角
大数据·科技·算法·架构
Qt程序员14 小时前
Linux RCU 原理与应用
linux·c++·内核·linux内核·rcu
想吃火锅100515 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
qeen8715 小时前
【C++】类与对象之类的默认成员函数(二)
android·c语言·开发语言·c++·笔记·学习