每日两道力扣,day3

每日两道力扣,day3

每日两道力扣,day3

每日两道力扣,今日是:

LCR 173. 点名 - 力扣(LeetCode)

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

第一题:点名

LCR 173. 点名 - 力扣(LeetCode)

1.思路:

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

方法一:

1.遍历找第一个不匹配的位置 < == >if (records[i] != 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)如果nums[mid] > nums[right],mid 在左侧的高斜坡,最小值肯定在右边,left = mid + 1。让mid往右走一点

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

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

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

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

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

(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; 来防止数据溢出

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

相关推荐
Yzzz-F4 小时前
Problem - 2146D1 - Codeforces &&Problem - D2 - Codeforces
算法
Kk.08024 小时前
力扣 LCR 084.全排列||
算法·leetcode·职场和发展
环黄金线HHJX.4 小时前
龙虾钳足启发的AI集群语言交互新范式
开发语言·人工智能·算法·编辑器·交互
Omics Pro4 小时前
虚拟细胞:开启HIV/AIDS治疗新纪元的关键?
大数据·数据库·人工智能·深度学习·算法·机器学习·计算机视觉
旖-旎4 小时前
分治(快速选择算法)(3)
c++·算法·leetcode·排序算法·快速选择
_日拱一卒5 小时前
LeetCode:合并区间
算法·leetcode·职场和发展
xiaoye-duck5 小时前
【C++:哈希表封装】哈希表封装 myunordered_map/myunordered_set 实战:底层原理 + 完整实现
数据结构·c++·散列表
汀、人工智能5 小时前
[特殊字符] 第3课:最长连续序列
数据结构·算法·数据库架构·图论·bfs·最长连续序列
少许极端5 小时前
算法奇妙屋(四十一)-贪心算法学习之路 8
学习·算法·贪心算法
A.A呐5 小时前
【C++第二十三章】C++11
开发语言·c++