二分套路 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jiong-952

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值