二分法模板以及例题 (二)

这篇全是例题,模板在上文
二分法模板以及例题 (一)
34. 在排序数组中查找元素的第一个和最后一个位置
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
解题思路:模板一模板二分别使用一次

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

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

    
    
};

35. 搜索插入位置
输入: nums = [1,3,5,6], target = 5
输出: 2
解题思路:简单题找到第一小于等于目标值的位置,直接使用模板一

class Solution {
public:
    bool check(int x,int p){
        //找到第一个大于等于
        if(x>=p)
            return true;
        return false;
    }
    int searchInsert(vector<int>& nums, int target) {
        int l,r,mid;
        l= 0;
        r= nums.size();
        while(l<r){
            mid = (l+r) >>1;
            if(check(nums[mid],target))
            {
                r = mid;
            }else{
                l = mid +1;
            }
        }
        return l;
    }
};

69. x 的平方根
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842…, 由于返回类型是整数,小数部分将被舍去。
解题思路:这题就类似于[1,2,3,4,5,6,7,8]
2^2 <8
3^2 >8
要找到第一个小于等于8的值,前面是比之,这题是比平方后的值,万变不离其宗,因为数不会重复,所以模板一二都可以

class Solution {
public:
    int mySqrt(int x) {
        int r,l,mid;
        l=0;r=x;
        while(l<r){
            mid=(r-l)/2+l+1;
            if(mid>x/mid){
                r=mid-1;
            }else{
                l=mid;
            }
        }
        return l;
    }
};

74. 搜索二维矩阵
二分法模板以及例题 (二)_第1张图片
矩阵是从左往右递增,从上往下递增,寻找一个数
解题思路:

  1. 二分法暴力一点就是,第一次行二分一次,第二次找列二分一次
  2. 使用双指针可以很容易秒杀这题,i和j从右上角开始移动,每次排除一行或者一列
  3. 二分法 的思路类似于压缩矩阵,把二维的拍平一维做二分查找

l最小等于0
r最大n*m-1
mid/m确定当前行
mid%m确定当前列

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if(matrix.empty()||matrix[0].empty())return false;
        int l,r;
        int n=matrix.size(),m=matrix[0].size();
        l=0,r=n*m-1;
        while(l<r){
            int mid=(l+r+1)>>1;
            if(matrix[mid/m][mid%m]<=target){
                l=mid;
            }else{
                r=mid-1;
            }
        }
        return matrix[l/m][l%m]==target;
    }
};

153. 寻找旋转排序数组中的最小值
这题是二分法模板以及例题 (一)中例题的简单版了,只需要找到分段的位置
33. 搜索旋转排序数组

class Solution {
public:
    int findMin(vector<int>& nums) {
        int l,r;
        l=0;r=nums.size()-1;
        while(l<r){
            int mid=l+(long long)r>>1;
            if(nums[mid]<=nums.back()){
                r=mid;
            }
            else{
                l=mid+1;
            }
        }
        return nums[l];
    }
};

162. 寻找峰值
输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5
解释:你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
解题思路:需要一个先增后降的位置,即如果找到是递增的则排除左边,如果找到是递减的则排除右边,峰不会重复,如[1,2,2,1]这样,所以模板一二都可以

class Solution {
    public int findPeakElement(int[] nums) {
        int l = 0, r = nums.length - 1;
        while (l < r) {
            int mid = l + ((r - l) >> 1);
            if (nums[mid] < nums[mid+1]) {
                l = mid + 1;
            } else {
                r = mid;
            }
        }
        return l;
    }
}

你可能感兴趣的:(算法,算法,leetcode,数据结构)