每日两道力扣,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; 来防止数据溢出

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

相关推荐
lwf0061643 分钟前
导数学习日记
学习·算法·机器学习
头发够用的程序员1 小时前
从滑动窗口到矩阵运算:img2col算法基本原理
人工智能·算法·yolo·性能优化·矩阵·边缘计算·jetson
武帝为此1 小时前
【数据清洗缺失值处理】
python·算法·数学建模
Halo_tjn2 小时前
Java 基于字符串相关知识点
java·开发语言·算法
念越2 小时前
算法每日一题 Day08|双指针法解决三数之和
算法·力扣
万法若空2 小时前
C++ <memory> 库全方位详解
开发语言·c++
黎阳之光3 小时前
黎阳之光透明管理:视频孪生重构智慧仓储新范式
人工智能·算法·安全·重构·数字孪生
代码中介商3 小时前
C++ 类型转换深度解析:static_cast、dynamic_cast、const_cast、reinterpret_cast
开发语言·c++
青小莫3 小时前
C++之string(OJ练习)
开发语言·c++·stl
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 199. 二叉树的右视图 | C++ DFS 逆序遍历
c++·leetcode·深度优先