二分套路 y神模板

二分套路

y神模板

b站链接:https://www.bilibili.com/video/BV1Ft41157zW/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=5500fef761fd3ab451b9bbe518cd5cc6

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1qwvq0iA-1666616253853)(img/0828e07b342f41eab6b179283dcd91aa.png)]

模板一

int bsearch_1(int l, int r)
{
    
    
    while (l < r)
    {
    
    
        int mid = l + r >> 1; //除2 操作
        if (check(mid)) r = mid; //check函数即为边界的选择
        else l = mid + 1;
    }
    return l; //l r都可以,跳出while r = l
}

模板二

int bsearch_2(int l, int r)
{
    
    
    while (l < r)
    {
    
    
        int mid = l + r + 1 >> 1; //注意+1操作
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

实战

lc.x的平方根https://leetcode.cn/problems/sqrtx/description/

class Solution {
    
    
    public int mySqrt(int x) {
    
    
        //套y神模板
        int l = 0, r = x;
        while(l < r){
    
    
            int mid = (l + r + 1) >> 1;
            if(mid <= x / mid){
    
    
                l = mid;
            }else{
    
    
                r = mid - 1;
            }
        }
        return r;
    }
}

lc74 搜索二维矩阵 https://leetcode.cn/problems/search-a-2d-matrix/

class Solution {
    
    
    public boolean searchMatrix(int[][] matrix, int target) {
    
    
        //使用y神模板
        if(matrix == null || matrix.length == 0) return false;
        int n = matrix.length, m = matrix[0].length;
        int l = 0, r = n * m - 1;
        while(l < r){
    
    
            int mid = (l + r) >> 1;
            if(matrix[mid / m][mid % m] >= target){
    
    
                r = mid;
            }else{
    
    
                l = mid + 1;
            }
        }
        if(matrix[r / m][r % m] != target) return false;
        return true;
    }
}

lc35 搜索插入位置https://leetcode.cn/problems/search-insert-position/description/

public int searchInsert(int[] nums, int target) {
    
    
        //O(logn)很明显的二分
        int l = 0,r = nums.length;
        while(l < r){
    
    
            int mid = (l + r) >> 1;
            if(nums[mid] >= target){
    
    
                r = mid;
            }else{
    
    
                l = mid + 1;
            }
        }
        return r;
    }

lc34. 在排序数组中查找元素的第一个和最后一个位置https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/

class Solution {
    
    
    public int[] searchRange(int[] nums, int target) {
    
    
        //O(logn)二分
        //两个模板一起用
        if(nums.length == 0 || nums == null) return new int[]{
    
    -1,-1};
        int l = 0, r = nums.length - 1;
        //先找start
        while(l < r){
    
    
            int mid = (l + r) >> 1;
            if(nums[mid] >= target){
    
    
                r = mid;
            }else{
    
    
                l = mid + 1;
            }
        }
        if(nums[r] != target) return new int[]{
    
    -1,-1};
        int start = r;
        //找end
        l = 0;
        r = nums.length - 1;
        while(l < r){
    
    
            int mid = (l + r + 1) >> 1;
            if(nums[mid] <= target){
    
    
                l = mid;
            }else{
    
    
                r = mid - 1;
            }
        }
        int end = l;
        return new int[]{
    
    start,end};
    }
}

lc153. 寻找旋转排序数组中的最小值https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/description/

class Solution {
    
    
    public int findMin(int[] nums) {
    
    
        //找一个状态能够二段性
        int n = nums.length;
        int l = 0, r = n - 1;
        while(l < r){
    
    
            int mid = (l + r) >> 1;
            if(nums[mid] < nums[n - 1]){
    
    
                r = mid;
            }else{
    
    
                l = mid + 1;
            }
        }
        return nums[l];
    }
}

lc33 搜索旋转排序数组https://leetcode.cn/problems/search-in-rotated-sorted-array/description/

class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        //先找出最小值的下标
        int minIndex = findMinIndex(nums);
        System.out.println(minIndex);
        if(target <= nums[nums.length - 1]){
    
    
            //后半段
            return binarySearch(nums,target,minIndex,nums.length - 1);
        }else{
    
    
            //前半段
            return binarySearch(nums,target,0,minIndex - 1);
        }
    }
    public int binarySearch(int[] nums, int target, int left, int right){
    
    
        int l = left, r = right;
        while(l < r){
    
    
            int mid = (l + r) >> 1;
            if(nums[mid] >= target){
    
    
                r = mid;
            }else{
    
    
                l = mid + 1;
            }
        }
        System.out.println(l);
        if(nums[l] == target) return l;
        return -1;
    }
    public int findMinIndex(int[] nums) {
    
    
        //找一个状态能够二段性
        int n = nums.length;
        int l = 0, r = n - 1;
        while(l < r){
    
    
            int mid = (l + r) >> 1;
            if(nums[mid] < nums[n - 1]){
    
    
                r = mid;
            }else{
    
    
                l = mid + 1;
            }
        }
        return l;
    }
}
  • 总结nums[mid] >= target可以用于找第一个出现的target值 不存在则返回-1
  • nums[mid] <= target可以用于找最后一个出现的target值 不存在则返回-1

猜你喜欢

转载自blog.csdn.net/weixin_51712663/article/details/127501296
今日推荐