Leetcode数组 二分查找 双指针 704 34 35 27 167 26 283

704. Binary Search

可以用二分法的两个条件:

1.数组是有序的

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;
            if(nums[mid] == target)
                return mid;
            if(nums[mid] > target){
                right = mid-1;
            }else{
                left = mid+1;
            }
        }
        return -1;
    }
};

注意区间:

当right = nums.size()-1;就意味着这时一个左闭右闭的区间,相应的 循环条件为 left <= right,

left和right的取值也为mid+1 和mid-1

35. Search Insert Position

左闭右闭和左闭右开都试了一下,这道题感觉左闭右开比较好一些,若是左闭右闭,需要进行边界条件的判断

左闭右开:

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

        
    }
};

左闭右闭:

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

两个小问题:

1.left < 0是不需要判断的

2.右边超出边界值的条件是>= nums.size()

34. Find First and Last Position of Element in Sorted Array

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = left_bound(nums, target);
        int right = right_bound(nums, target);
        return {left, right};
    }

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

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

依旧是判断边界的时候出现了问题

可以这样理解:当寻找做边界的时候是右边在动,那么左侧就是准确的,左侧只会越来越大,那么只需要看left是否超过右边界即可。因为left是准确的,所以返回左侧的值,返回left即可。

当寻找右边界的时候,左侧在动,那么右边的是准确的,因为right为开,所以返回的是left-1(或者right-1)

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = left_bound(nums, target);
        int right = right_bound(nums, target);
        return {left, right};
    }

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

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

27. Remove Element

快慢指针

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slow = 0, fast = 0;
        while(fast < nums.size()){
            if(nums[fast] != val){
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }

        return slow;
    }
};

167. Two Sum II - Input Array Is Sorted

左右指针

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int left =0, right = numbers.size()-1;
        while(left < right){
            if(numbers[left]+numbers[right] == target)
                return {left+1, right+1};
            else if(numbers[left]+numbers[right] > target)
                right--;
            else left++;
        }
    return {-1, -1};
    }
};

需要的限定条件:

1.有序且无重复的数组

2.只有一组答案

注意:

index从1开始

26. Remove Duplicates from Sorted Array

快慢指针

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int slow = 0, fast = 0;
        while(fast < nums.size()){
            if(nums[fast] != nums[slow]){
                slow++;
                nums[slow] = nums[fast];
            }
            fast++;
        }
        return slow+1;
    }
};

注意:

这里要先slow++再赋值

283. Move Zeroes

快慢指针

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow =0, fast =0;
        while(fast < nums.size()){
            if(nums[fast] != 0){
                nums[slow] = nums[fast];
                slow++;
            }
            fast++;
        }
        for(int i = slow; i<nums.size(); i++)
            nums[i] = 0;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值