算法总结(二分查找、双指针)

引言

题目链接

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

27. 移除元素 - 力扣(LeetCode)

977. 有序数组的平方 - 力扣(LeetCode)

69. x 的平方根 - 力扣(LeetCode)

第一题

这一题只要就是要我们用二分查找来实现一个对于左右区间的查找。这个和我们之前遇到的都不太一样,因为我们二分查找一般都是一个值。

所以我们就拿左区间 来举例子。我们这里选择的写法是 。假设我们要找8,【6 8 8 9】,我们要注意的是,二分查找法的目的是找一个值,所以那我们如果是左区间,就要让右边界right不断地往左边去靠,【8 8 8 8 8】假设我们的8很多,这个时候我们应该不断地移动right,所以这里地判断条件是numsmid >= target,同时把左边界赋值。**直到最后一个,**这个时候right--了,破坏了while的条件,但关键是这个操作仍然进行了,所以right最后一个指向其实是左边界地前面一个。所以在主函数里面return {left + 1, right - 1};这个操作结果可能和我们之前想的不是很一样,是因为我们之前地条件是判断==,如果相等返回,一直没有就返回没找到,根本不需要看这个左右区间的。而这个地方,我们不需要看是否相等,因为这个没有意义。

最后对于这个左右区间的结果处理,也比较有意思。因为如果target根本不在这个区间里面,那么left和right其中必定有一个是-2,假设我们在最右边,那么在计算左区间的时候,右边界根本不会移动。还有一种就是target没有找到,那这是最后一种情况,自然返回-1了

cpp 复制代码
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = searchLeft(nums, target);
        int right = searchRight(nums, target);
        if(left == -2 || right == -2) {
            return {-1, -1};
        }
        if(right - left > 1) {
            return {left + 1, right - 1};
        }
        return {-1, -1};
    }

private:
    int searchLeft(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        int leftRange = -2;
        while(left <= right) {
            int mid = left + ((right - left) / 2);
            if(nums[mid] >= target) {
                right = mid - 1;
                leftRange = right;
            } else {
                left = mid + 1;
            }
        }
        return leftRange;
    }

    int searchRight(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        int rightRange = -2;
        while(left <= right) {
            int mid = left + ((right - left) / 2);
            if(nums[mid] <= target) {
                left = mid + 1;
                rightRange = left;
            } else {
                right = mid - 1;
            }
        }
        return rightRange;
    }
};

第二题

相对于两层for循环,一般来说,双指针可以完全代替两层for循环,用时间复杂度为O(n)的代码来解决问题

双指针的问题,本质上是一个快指针,一个慢指针。

在这一题里面,快指针的作用就是遍历整个数组,而慢指针的作用就是跟在屁股后面更新整个数组,凡是不对的,快指针跳过去,不让慢指针更新

cpp 复制代码
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slow = 0;
        for(int fast = 0; fast < nums.size(); fast++) {
            if(nums[fast] != val) {
                nums[slow] = nums[fast];
                slow++;
            } 
        }
        return slow;
    }
};

第三题

这个题要求的是把每个数平方之后再排序,因为数组原来就是有序的,但是因为负数的存在,所以最大的数永远是来自于最两侧,所以我们用left和right来表示最两侧的数据,然后每一次都选出最大的那一个数据,放入我们的新数组中res,也就是说我们的新数组是从最后面开始写入数据的。不过要注意的是我们结束的条件是left <= right,如果没有等于号,那么就会漏掉left和right相等时的那一个数据。

这里的k是新数组插入的索引

cpp 复制代码
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int k = nums.size() - 1;
        vector<int> res(nums.size(), 0);
        for(int left = 0, right = nums.size() - 1; left <= right; ) {
            if(nums[left] * nums[left] < nums[right] * nums[right]) {
                res[k] = nums[right] * nums[right];
                right--;
                k--;
            } else {
                res[k] = nums[left] * nums[left];
                left++;
                k--;
            }
        }
        return res;
    }
};

第四题

这一题给我们了一个思路来求一个数的算数平方根。

我们还是可以用二分查找法来求,但是这个题目的要求是向下取整,所以我们需要对二分查找发有更加深刻的认识

首先我们的答案需要单独来计算,用ans,之前我们可以返回left,但是这里不可以,因为我们二分查找法找的是一个定值,但是这里一般都是小数,所以定值不存在,既然定值不存在,就不能在特定的位置返回,就不能得到我们想要的答案。所以我们记录ans的值,因为我们是不断的利用mid*mid来判断的,自然而然,mid就是我们最后要的答案。

注意一下,我们这里必须要在去等的地方对ans赋值,因为如果刚好相等了,但是你把这个值给跳过去了,那不是玩蛋蛋~~~

cpp 复制代码
class Solution {
public:
    int mySqrt(int x) {
        int left = 0;
        int right = x;
        int ans = -1;
        while(left <= right) {
            int mid = left + (right - left) / 2;
            if((long long)mid * mid <= x) {
                left = mid + 1;
                ans = mid;
            } else {
                right = mid - 1;
            }
        }
        return ans;
    }
};

总结

本篇主要是针对二分查找和双指针来记录的。希望可以对大家有所帮助!!!

相关推荐
qq_8573058191 小时前
python语法
开发语言·python·算法
DXM05212 小时前
第9期|从机器学习到深度学习:AI遥感解译的进化逻辑
人工智能·算法·计算机视觉
小蒋学算法2 小时前
算法-阶乘函数后K个零
算法
weixin_307779132 小时前
智能模拟数据生成平台:生成式AI合成数据技术重塑开发测试效能
人工智能·测试工具·算法·测试用例
不负岁月无痕2 小时前
C++ 模板核心内容与高频面试题汇总
java·开发语言·c++
无限进步_3 小时前
从零实现一个迷你Shell——深入理解Linux命令行解释器
linux·运维·服务器·开发语言·c++·chrome
羊羊小栈3 小时前
Uplift营销供应链协同决策系统(基于Uplift因果推断与运筹优化算法)
前端·人工智能·算法·毕业设计·大作业
fpcc3 小时前
工具使用——CMake中的函数和宏
c++·cmake
金融小师妹3 小时前
AI因子共振模型显示:金银比突破区间上沿,白银定价逻辑进入再校准阶段
人工智能·算法·均值算法·线性回归