Leetcode二分查找/双指针

704 二分查找

如果把相等的情况放在第一个判断,Leetcode第16个测试用例会超时。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l=0,r=nums.size()-1;
        while(l<=r){// 条件不能为(l<r),当nums长度为1且该元素与target相等时,会跳过循环返回-1
            int m=(l+r)/2; // m=l+(r-l)/2可以防止溢出
            if(nums[m]>target){// target在nums[m]左边
                r=m-1;
            }else if(nums[m]==target){
                return m;
            }else{// target在nums[m]右边
                l=m+1;
            }
        }
        return -1; 
    }
};

34 在排序数组中查找元素的第一个和最后一个位置

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        // 题目理解错误,下标可以一样,即target出现一次
        int l=0,r=nums.size()-1;
        while(l<=r){// 条件不能为l<r,会跳过长度为1的数组
            int m=l+(r-l)/2;
            if(target<nums[m]){
                r=m-1;
            }else if(target>nums[m]){
                l=m+1;
            }else{//target==nums[m],由于target连续,用while循环把左右指针移动至两端的target处
                while(nums[l]!=target){
                    l++;
                }
                while(nums[r]!=target){
                    r--;
                }
                return {l,r};
            }
        }
        return {-1,-1};
    }
};

162 寻找峰值

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        // 寻找max
        // return max_element(nums.begin(),nums.end())-nums.begin();
        if (nums.size() == 1) {
            return 0;
        }
        if (nums.size() == 2) {
            return (nums[0] < nums[1]) ? 1 : 0;
        }
        int l = 0, r = nums.size() - 1;
        while (l < r) {
            int m = (l+r) / 2;
            // 写成 int m= l+(r-l)/2; 时,leetcode测试用例[1,2,3,1]会越界
            if (nums[m] > nums[m + 1]) {//往[l,m]继续找
                r = m;
            }
            else {//往[m+1,r]继续找
                l = m + 1;
            }
        }
        return l;

    }
};

74 搜索二维矩阵

先判断target是否位于矩阵包含的区间中,再用二分查找的方法判断在哪一行,最后进行二分查找。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int l = 0, r = nums.size() - 1;
        while (l <= r) {// 条件不能为(l<r),当nums长度为1且该元素与target相等时,会跳过循环返回-1
            int m = (l + r) / 2;
            if (nums[m] > target) {// target在nums[m]左边
                r = m - 1;
            }
            else if (nums[m] == target) {
                return m;
            }
            else {// target在nums[m]右边
                l = m + 1;
            }
        }
        return -1;
    }

    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        if ((matrix[m - 1][n - 1] < target) || (matrix[0][0] > target)) {
            return false;
        }
        int l = 0, r = m - 1;
        int target_column = 0;//行定位
        while (l <= r) {
            // int m = l + (r - 1) / 2;//z这里第二个字母l写成了数字1,报错了
            //Line 1037: Char 9: runtime error: reference binding to misaligned address 0xbebebebebebebebe for type 'int', which requires 4 byte alignment (stl_vector.h)
            int mid = l + (r - l) / 2;
            if (matrix[mid][0] > target) {
                r = mid - 1;
            }
            else if ((matrix[mid][0] <= target) && (target <= matrix[mid][n - 1])) {
                target_column = mid;
                break;
            }
            else {
                l = mid + 1;
            }
        }

        int target_row = search(matrix[target_column], target);//二分查找
        return (target_row == -1) ? false : true;
    }
};

153 寻找旋转排序数组中的最小值

class Solution {
public:
    int findMin(vector<int>& nums) {
        if(nums.size()==1){
            return nums[0];
        }
        int l=1,r=nums.size()-1;//l=1是因为下面的while循环要用到nums[m-1],防止数组越界
        //旋转n次的数组,即原数组,元素单调递增
        if(nums[0]<nums[r]&&nums[0]<nums[1]){
            return nums[0];
        }
        //旋转[1,n-1]次的数组
        while(l<=r){
            int m=l+(r-l)/2;
            if(nums[m-1]>nums[m]){//旋转[1,n-1]次的数组,一定会出现一次降序
                return nums[m];
            }
            if(nums[m-1]<nums[m]&&nums[0]<nums[m]){
                l=m+1;
            }else{
                r=m;
            }
        }
        return 0;
    }
};

15.三数之和

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        if ((nums.size() <= 2)) {
            return ans;
        }
        
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for (int i = 0; i < n - 2; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) { //跳过连续相等的值
                continue;
            }
            int left = i + 1;
            int right = n - 1;
            while (left < right) {
                if (nums[i] + nums[left] + nums[right] == 0) {
                    ans.push_back({nums[i], nums[left], nums[right]});
                    while (left < right && nums[left] == nums[left + 1])//跳过连续相等的值
                        left++;
                    while (left < right && nums[right] == nums[right - 1])//跳过连续相等的值
                        right--;
                    left++;//此时nums[left]与原来的不相等,nums[right]同理
                    right--;
                } else if (nums[i] + nums[left] + nums[right] < 0) {
                    left++;
                } else {
                    right--;
                }
            }
        }
        return ans;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值