当前位置:   article > 正文

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

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

二分查找

lc704

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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

lc35

  • lc35
  • 思路:手写lower_bound
  • 代码
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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

lc34

  • lc34
  • 和y总的二分例题一样
  • 代码
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};
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

lc69

  • lc69
  • 回忆浮点数二分:保证一定精度内正确;但这题使用整数二分即可
  • 代码
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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

lc367

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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

快慢指针

lc27

  • lc27
  • 暴力解:双重for,遍历到val就全部元素往前移一个位置,时间复杂度为O(n^2)
  • 优化思路:弄懂快慢指针含义即可,时间复杂度为O(n)
    • fast: 原数组位置,寻找不为val值的元素
    • slow:最终的目标数组位置
    • 变化:fast指向的不是val的元素放到slow处
  • 代码
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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

lc26

  • 题目
  • 上一题的变形,主要理解快慢指针的含义和他们之间的关系
  • 代码
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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

lc844

  • lc844
  • 思路1:利用上面快慢指针的思想,分别得到两个最终的字符串后,再比较,时间复杂度为O(n+m);也可以用栈的思路获取最终的字符串
  • 代码:
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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

lc977

  • lc977
  • 思路:相向指针,因为负数平方从大到小,正数平方从小到大;两个指针比较即两个数的平方比较,大的一个放到目标数组中
  • 代码
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;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/561224
推荐阅读
相关标签
  

闽ICP备14008679号