代码随想录:二分查找和双指针

二分查找

lc704

c 复制代码
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while(left < right){
            int mid = (left + right) >> 1;  // 可以写成mid = left + (right - left) >> 1
            if(nums[mid] >= target){
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        if(nums[left] == target){
            return left;
        }
        return -1;
    }
};

lc35

  • lc35
  • 思路:手写lower_bound
  • 代码
c 复制代码
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        // 找第一个>=target的位置
        int left = 0, right = nums.size();
        while(left < right){
            int mid = (left + right) >> 1;
            if(nums[mid] >= target){
                right = mid;
            } else{
                left = mid + 1;
            }
        }
        return left;
    }
};

lc34

  • lc34
  • 和y总的二分例题一样
  • 代码
c 复制代码
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty()){
            return {-1, -1};
        }
        // lower_bound和upper_bound,注意二分计算时mid的溢出
        // 1. 第一个位置
        int left = 0, right = nums.size() - 1;
        while(left < right){
            int mid = left + (right - left) / 2;
            if(nums[mid] >= target){
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        if(nums[left] != target){
            // 返回[-1, -1]
            return {-1, -1};
        }
        int first = left;  // 记录第一个位置
        left = 0, right = nums.size() - 1;
        // 2. 最后一个位置
        while(left < right){
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] <= target){
                left = mid;
            }else{
                right = mid - 1;
            }
        }
        // 返回结果
        return {first, left};
    }
};

lc69

  • lc69
  • 回忆浮点数二分:保证一定精度内正确;但这题使用整数二分即可
  • 代码
c 复制代码
class Solution {
public:
    int mySqrt(int x) {
        int left = 0, right = 1e9;
        while(left < right){
            int mid = (right + left + 1) / 2;
            if((long long)mid * mid <= x){  // 舍去小数,所以找小于的一边
                left = mid;
            }else{
                right = mid - 1;
            }
        }
        return left;
    }
};

lc367

c 复制代码
class Solution {
public:
    bool isPerfectSquare(int num) {
        // 暴力:遍历所有int看是否平方 == num;所以使用二分简化
        int left = 1, right = 1e9;
        while(left < right){
            int mid = (left + right) >> 1;
            if((long long)mid * mid >= num){
                right = mid;
            }else{
                left = mid + 1;
            }
        }
        if((long long)left * left == num){
            return true;
        }
        return false;
    }
};

快慢指针

lc27

  • lc27
  • 暴力解:双重for,遍历到val就全部元素往前移一个位置,时间复杂度为O(n^2)
  • 优化思路:弄懂快慢指针含义即可,时间复杂度为O(n)
    • fast: 原数组位置,寻找不为val值的元素
    • slow:最终的目标数组位置
    • 变化:fast指向的不是val的元素放到slow处
  • 代码
c 复制代码
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int fast = 0, slow = 0; 
        for(; fast < nums.size(); fast++){
            if(val != nums[fast]){
                nums[slow++] = nums[fast];
            }
        }
        return slow;
    }
};

lc26

  • 题目
  • 上一题的变形,主要理解快慢指针的含义和他们之间的关系
  • 代码
c 复制代码
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.empty()){
            return 0;
        }
        // 快指针:指向原数组,找到第一个不同的元素
        // 慢指针:指向结果数组的位置
        // 如果nums[fast] != nums[fast - 1],就把这个不重复元素送到slow位置
        int slow = 1, fast = 1;
        for(; fast < nums.size(); fast++){
            if(nums[fast] != nums[fast -1]){
                nums[slow++] = nums[fast];
            }
        }
        return slow;
    }
};

lc844

  • lc844
  • 思路1:利用上面快慢指针的思想,分别得到两个最终的字符串后,再比较,时间复杂度为O(n+m);也可以用栈的思路获取最终的字符串
  • 代码:
c 复制代码
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        // 1. 先去掉退格字符
        int change_s = changeString(s);
        int change_t = changeString(t);
        cout << "s = " << s << " t = " << t << endl;
        cout << change_s << ' ' << change_t << endl;
        // 2. 比较前几个字符是否相同
        if(change_s != change_t){
            return false;
        }
        for(int i = 0; i < change_s; i++){
            if(s[i] != t[i]){
                return false;
            }
        }
        return true;
    }
    int changeString(string &str){
        // 返回前几个字符是有效的
        int slow = 0, fast = 0;
        for(; fast < str.size(); fast++){
            if(str[fast] == '#'){
                if(slow != 0){  // 如果slow已经在开头,不用动
                    --slow;
                }
            } else{
                str[slow++] = str[fast];
            }
        }
        return slow;
    }
};

lc977

  • lc977
  • 思路:相向指针,因为负数平方从大到小,正数平方从小到大;两个指针比较即两个数的平方比较,大的一个放到目标数组中
  • 代码
c 复制代码
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        // 暴力:平方后排序
        // for(auto &i : nums){
        //     i = i * i;
        // }
        // sort(nums.begin(), nums.end());
        // return nums;
        // 双指针:两头指针,大的放到后面
        int n_size = nums.size() - 1;
        vector<int> ret(n_size + 1);
        for(int i = 0, j = n_size, pos = n_size; i <= j; ){
            if(nums[i] * nums[i] <= nums[j] * nums[j]){
                ret[pos--] = nums[j] * nums[j];
                j--;
            } else{
                ret[pos--] = nums[i] * nums[i];
                i++;
            }
        }
        return ret;
    }
};
相关推荐
若亦_Royi34 分钟前
C++ 的大括号的用法合集
开发语言·c++
Captain823Jack1 小时前
nlp新词发现——浅析 TF·IDF
人工智能·python·深度学习·神经网络·算法·自然语言处理
Captain823Jack2 小时前
w04_nlp大模型训练·中文分词
人工智能·python·深度学习·神经网络·算法·自然语言处理·中文分词
是小胡嘛2 小时前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_748255022 小时前
前端常用算法集合
前端·算法
呆呆的猫3 小时前
【LeetCode】227、基本计算器 II
算法·leetcode·职场和发展
Tisfy3 小时前
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
算法·leetcode·优先队列·贪心·
余额不足121383 小时前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
ragnwang4 小时前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
火星机器人life5 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d