LeetCode中使用二分查找法的题目的整理(待更)

本文整理了LeetCode中使用二分查找法的题目,包括简单、中等和困难难度,涵盖搜索、排序数组、旋转数组、平方根、完全平方数等问题,附带相关解题链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找(simple难度)

https://leetcode-cn.com/problems/binary-search/

class Solution {
    public int binarySearch(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;//注意,左闭右闭区间,所以right = len - 1
        // 目标元素可能在 左闭右闭 区间:[left, right],但下面while循环是 < 而不是 <= ,要注意
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                // 下一轮搜索区间是 [mid + 1, right],索引mid对应元素一定不符合要求,所以左边界是mid+1
                left = mid + 1;
            } else {
                // 下一轮搜索区间是 [left, mid],索引mid对应元素可能不符合要求,所以右边界是mid
                right = mid;
            }
        }

        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
}

或者:

class Solution {
    public int binarySearch(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;
        // 定义target在 左闭右闭 的区间里,[left, right]
        //若if (nums[mid] == target) 在while内判断,则是left <= right
        //若不在while内判断相等时的情况,则是left < right
        while (left <= right) {// 当left==right,区间[left, right]依然有效
            int mid = left + (right - left) / 2;    //防止溢出,等同于(left + right)/2
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                //因为target要在左闭右闭的区间里,因为nums[mid]不满足条件,
                //所以要把mid从区间里剔除,所以搜索区间变为[mid + 1, right]
                left = mid + 1; // target在右区间,所以[mid + 1, right]
            } else {
                right = mid - 1;    // target在左区间,所以[left, mid - 1]
            }
        }
        return -1;
    }
}

第一个错误的版本(simple难度)

https://leetcode-cn.com/problems/first-bad-version/

/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left = 1;
        int right = n;
        while (left < right){
            int mid = left + (right - left) / 2;
            if(isBadVersion(mid) == false){
                left = mid + 1;
            }else{
                right = mid;
            }
        }
        return left;
    }
}

猜数字大小(simple难度)

https://leetcode-cn.com/problems/guess-number-higher-or-lower/

/** 
 * Forward declaration of guess API.
 * @param  num   your guess
 * @return 	     -1 if num is lower than the guess number
 *			      1 if num is higher than the guess number
 *               otherwise return 0
 * int guess(int num);
 */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        int left = 1;
        int right = n;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if(guess(mid) == 0){
                return mid;
            }else if(guess(mid) == -1){
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return left; 
    }
}

排列硬币(simple难度)

https://leetcode-cn.com/problems/arranging-coins/

排列硬币可以转化成寻找 <=n 的最大等差数列和的尾项。
细节看代码注释。

class Solution {
    public int arrangeCoins(int n) {
        long left = 0;
        long right = n;
        while (left < right) {
            long mid = left + (right - left + 1) / 2;
            //硬币排列类似等差数列求和
            //等差数列求和公式:(首项 + 尾项) * 项数 / 2
            //本题中首项为1,尾项为mid,项数也为mid
            //本题要满足:(首项 + 尾项) * 项数 / 2 <= n
            //整理可得:mid * (mid + 1) <= 2 * n
            if (mid * (mid + 1) > (long) 2 * n) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return (int) left;
    }
}

搜索插入位置(simple难度)

https://leetcode-cn.com/problems/search-insert-position/

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        int left = 0;
        int right = n - 1; // 定义target在左闭右闭的区间里,[left, right] 
        while (left <= right) { // 当left==right,区间[left, right]依然有效
            int mid = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[mid] > target) {
                right = mid - 1; // target 在左区间,所以[left, mid - 1]
            } else if (nums[mid] < target) {
                left = mid + 1; // target 在右区间,所以[mid + 1, right]
            } else { // nums[mid] == target
                return mid;
            }
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return mid;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], return right + 1
        return right + 1;
    }
}

或:

public class Solution {

    public int searchInsert(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return 0;
        }

        // 特判
        if (nums[len - 1] < target) {
            return len;
        }
        int left = 0;
        int right = len - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            // 严格小于 target 的元素一定不是解
            if (nums[mid] < target) {
                // 下一轮搜索区间是 [mid + 1, right]
                left = mid + 1;
            } else {
                // 下一轮搜索区间是 [left, mid]
                right = mid;
            }
        }
        return left;
    }
}

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

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/si-lu-hen-jian-dan-xi-jie-fei-mo-gui-de-er-fen-cha/
来源:力扣(LeetCode)

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return new int[]{-1, -1};
        }
		//firstPosition == -1 说明数组中没有target,则返回[-1,-1]
        int firstPosition = findFirstPosition(nums, target);
        if (firstPosition == -1) {
            return new int[]{-1, -1};
        }

        int lastPosition = findLastPosition(nums, target);
        return new int[]{firstPosition, lastPosition};
    }
	//查找相同target值的左边界
    private int findFirstPosition(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            // 小于一定不是解
            if (nums[mid] < target) {
                // 下一轮搜索区间是 [mid + 1, right]
                left = mid + 1;
            } else if (nums[mid] == target) {
                // 下一轮搜索区间是 [left, mid],一直向左搜寻,找到左边界
                right = mid;
            } else {
                // nums[mid] > target,下一轮搜索区间是 [left, mid - 1]
                right = mid - 1;
            }
        }

        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
	//查找相同target值的右边界
    private int findLastPosition(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            if (nums[mid] > target) {
                // 下一轮搜索区间是 [left, mid - 1]
                right = mid - 1;
            } else if (nums[mid] == target){
                // 下一轮搜索区间是 [mid, right],一直向右搜寻,找到右边界
                left = mid;
            } else {
                // nums[mid] < target,下一轮搜索区间是 [mid + 1, right]
                left = mid + 1;
            }
        }
        return left;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/si-lu-hen-jian-dan-xi-jie-fei-mo-gui-de-er-fen-cha/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

搜索旋转排序数组(medium难度)

https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

<方法一>:

本题方法和代码来源:
作者:sweetiee
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/duo-si-lu-wan-quan-gong-lue-bi-xu-miao-dong-by-swe/
来源:力扣(LeetCode)

<方法二>:

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/er-fen-fa-python-dai-ma-java-dai-ma-by-liweiwei141/
来源:力扣(LeetCode)

让情况1和情况2保持一致不然选不出中位数

public class Solution {

    public int search(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return -1;
        }

        int left = 0;
        int right = len - 1;
        while (left < right) {

            int mid = left + (right - left  + 1) / 2;

            if (nums[mid] < nums[right]) {

                // 使用上取整的中间数,必须在上面的 mid 表达式的括号里 + 1
                if (nums[mid] <= target && target <= nums[right]) {
                    // 下一轮搜索区间是 [mid, right]
                    left = mid;
                } else {
                    // 只要上面对了,这个区间是上面区间的反面区间,下一轮搜索区间是 [left, mid - 1]
                    right = mid - 1;
                }

            } else {

                // [left, mid] 有序,但是为了和上一个 if 有同样的收缩行为,
                // 我们故意只认为 [left, mid - 1] 有序
                // 当区间只有 2 个元素的时候 int mid = (left + right + 1) >>> 1; 一定会取到右边
                // 此时 mid - 1 不会越界,就是这么刚刚好

                if (nums[left] <= target && target <= nums[mid - 1]) {
                    // 下一轮搜索区间是 [left, mid - 1]
                    right = mid - 1;
                } else {
                    // 下一轮搜索区间是 [mid, right]
                    left = mid;
                }
            }
        }

        // 有可能区间内不存在目标元素,因此还需做一次判断
        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/er-fen-fa-python-dai-ma-java-dai-ma-by-liweiwei141/
来源:力扣(LeetCode)

class Solution5 {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            // 先根据 nums[mid] 与 nums[left] 的关系判断 mid 是在左段还是右段
            // mid 是在左段
            //循环条件是 left<=right, 所以 mid 会等于 left
            if (nums[mid] >= nums[left]) {
                // 再判断 target 是在 mid 的左边还是右边,从而调整左右边界 left 和 right
                // target 是在mid的左边,开区间
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
                // mid 是在右段
            } else {
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}

搜索旋转排序数组Ⅱ(medium难度)

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/er-fen-cha-zhao-by-liweiwei1419/
来源:力扣(LeetCode)

本题数组不完全有序且含有重复元素

本题不能采用LeetCode33.搜索旋转排序数组的代码的原因如下图:

class Solution {
    public boolean search(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return false;
        }
        int left = 0;
        int right = len - 1;
        while (left < right) {
            int mid = (left + right) >>> 1;
            if (nums[mid] > nums[left]) {  //mid处在没被旋转的子数组中,[left,mid]有序,包括mid
                if (nums[left] <= target && target <= nums[mid]) {
                    // 落在前有序数组[left,mid]里
                    right = mid;
                    // 落在后数组[mid+1,right]里
                    left = mid + 1;
                }
            } else if (nums[mid] < nums[left]) { //此时mid处于被旋转的子数组中,[mid,right]有序
                // 让分支和上面分支一样
                if (nums[mid] < target && target <= nums[right]) {
                    //落在后数组[mid+1,right]里
                    left = mid + 1;
                } else {
                    //落在前数组[left,mid]里
                    right = mid;
                }
            } else {
                // nums[mid] == nums[left],此时要去掉重复元素。要排除掉左边界之前,先看一看左边界可以不可以排除
                if (nums[left] == target) {
                    return true;
                } else {
                    left = left + 1;
                }
            }
        }
        // 后处理,夹逼以后,还要判断一下,是不是 target
        return nums[left] == target;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/er-fen-cha-zhao-by-liweiwei1419/
来源:力扣(LeetCode)

public class Solution {

    // 中间的数与右边界比较

    public boolean search(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return false;
        }
        int left = 0;
        int right = len - 1;

        while (left < right) {
            int mid = (left + right + 1 ) >>> 1;
            if (nums[mid] < nums[right]) {
                // 10 11 4 5 6 7 8 9
                // 右边的一定是顺序数组,包括中间数
                if (nums[mid] <= target && target <= nums[right]) {
                    left = mid;
                } else {
                    right = mid - 1;
                }
            } else if (nums[mid] > nums[right]) {
                // 4 5 9  2
                // 左边是一定是顺序数组,包括中间数
                if (nums[left] <= target && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid;
                }
            }else {
                if(nums[right] == target){
                    return true;
                }
                right = right -1;
            }
        }
        return nums[left] == target;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/er-fen-cha-zhao-by-liweiwei1419/
来源:力扣(LeetCode)

寻找旋转排序数组中的最小值(medium难度)

https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/

class Solution {
    public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2; // 防止溢出
            //nums[mid]可能是最小值,所以区间缩小为[left,mid]
            if (nums[mid] < nums[right]) {
                right = mid;
            }else{
                //nums[mid] > nums[right]时,
                //nums[mid]不可能是最小值,所以区间缩小为[mid + 1.rght]
                left = mid + 1;
            }
        }
        return nums[left];
    }
}


作者:HIT_whc
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/solution/javaji-jian-er-fen-cha-zhao-shi-jian-ji-oiefi/
来源:力扣(LeetCode)

寻找旋转排序数组中的最小值Ⅱ(hard难度)

https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/

在上道题LeetCode153.寻找旋转排序数组中的最小值的题解的基础上,把nums[mid] == nums[right]单独拿出来考虑,并进行收缩边界。这样做的原因详见代码注释,在代码注释中结合力扣测试用例进行了说明。

class Solution {
    public int findMin(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            //[mid,right]升序,最小值在[left,mid]
            if (nums[mid] < nums[right]) {
                right = mid;
                //最小值在[mid+1,right]
            } else if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else {
                //nums[mid] == nums[right],有重复元素,
                //此时不好判断最小值在哪边,所以收缩右边界,去掉一个重复元素
                //例如[3,3,1,3],left=0,right=3,mid=0,,nums[mid] == nums[right],
                //若采用right = mid收缩边界,则[left,right]区间元素变成[3,3],错过最小值
                //例如[1,3,3]left=0,right=2,mid=1,nums[mid] == nums[right]
                //若left = mid + 1收缩边界,[left,right]区间元素变成[3],错过最小值
                right--;
            }
        }
        return nums[left];
    }
}

作者:HIT_whc
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/solution/javaji-jian-er-fen-cha-zhao-zhong-fu-yua-glhs/
来源:力扣(LeetCode)

本题方法和代码来源:
作者:jyd
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/solution/154-find-minimum-in-rotated-sorted-array-ii-by-jyd/
来源:力扣(LeetCode)

class Solution {
    public int findMin(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            if (nums[mid] > nums[right]) left = mid + 1;
            else if (nums[mid] < nums[right]) right = mid;
            else right = right - 1;
        }
        return nums[left];
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/solution/154-find-minimum-in-rotated-sorted-array-ii-by-jyd/
来源:力扣(LeetCode)

山脉数组的峰顶索引(simple难度)

class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            if (arr[mid] > arr[mid - 1]) {
                left = mid;
            } else {//arr[mid] < arr[mid - 1]
                right = mid - 1;
            }
        }
        return left;
    }
}

或:

public int peakIndexInMountainArray(int[] A) {
    // 1.[定左右]
    int l = 0;
    int r = A.length-1;
	
    // 2.[定区间]
    while (l <= r) {// [l,r]
        // 3.[取中值]
        int mid = l + (r-l)/2;
       
        // 4.[进退]
        if (A[mid+1] > A[mid]) {// 上坡
            l = mid + 1; // [爬坡]
        } else if (A[mid-1] > A[mid]){// 下坡
            r = mid - 1; // [返回坡顶]
        } else {
            return mid;
        }

    }
	
    // 5.[无功而返]
    return -1;

}

作者:CVBear
链接:https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/solution/man-hua-suan-fa-er-fen-cha-zhao-yi-shou-shi-jie-ju/
来源:力扣(LeetCode)

x的平方根(simple难度)

https://leetcode-cn.com/problems/sqrtx/

<方法一>:二分查找

class Solution {
    public int mySqrt(int x) {
        if (x == 0) {
            return 0;
        }
        long left = 1;
        long right = x;
        while (left < right) {
            long mid = left + (right - left + 1) / 2;
            if ( mid * mid <= x) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        return (int)left;
    }
}

<方法二>:牛顿迭代

本方法思路和代码来源:
作者:LOAFER
链接:https://leetcode-cn.com/problems/sqrtx/solution/niu-dun-die-dai-fa-by-loafer/
来源:力扣(LeetCode)

class Solution {
    int s;
    
 public int mySqrt(int x) {
     s=x;
     if(x==0) return 0;
    return ((int)(sqrts(x)));
  }
    
    public double sqrts(double x){
      double res = (x + s / x) / 2;
    if (res == x) {
      return x;
    } else {
      return sqrts(res);
    }
    } 
}

作者:LOAFER
链接:https://leetcode-cn.com/problems/sqrtx/solution/niu-dun-die-dai-fa-by-loafer/
来源:力扣(LeetCode)

有效的完全平方数(simple难度)

https://leetcode-cn.com/problems/valid-perfect-square/

class Solution {
    public boolean isPerfectSquare(int num) {
        long left = 0;
        long right = num;
        while (left < right) {
            long mid = left + (right - left + 1) / 2;
            long sum = mid * mid;
            if (sum <= num) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        return (left*left) == num;
    }
}

寻找右区间(medium难度)

https://leetcode-cn.com/problems/find-right-interval/

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-right-interval/solution/er-fen-cha-zhao-hong-hei-shu-by-liweiwei1419/
来源:力扣(LeetCode)

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Solution {

    public int[] findRightInterval(int[][] intervals) {
        int len = intervals.length;
        if (len == 0) {
            return new int[0];
        }

        // 对原始区间进行预处理,key:起点,value:索引
        // 题目中说:你可以假定这些区间都不具有相同的起始点
        Map<Integer, Integer> hashMap = new HashMap<>(len);

        int[] arr = new int[len];
        int[] res = new int[len];
        for (int i = 0; i < len; i++) {
            hashMap.put(intervals[i][0], i);
            arr[i] = intervals[i][0];
        }

        Arrays.sort(arr);

        for (int i = 0; i < len; i++) {
            int index = binarySearch(arr, intervals[i][1]);
            if (index == -1) {
                res[i] = -1;
            } else {
                res[i] = hashMap.get(arr[index]);
            }
        }
        return res;
    }

    /**
     * 查找第 1 个大于等于 target 的元素的索引
     *
     * @param arr
     * @param target
     * @return
     */
    private int binarySearch(int[] arr, int target) {
        int len = arr.length;
        // 特判
        if (arr[len - 1] < target) {
            return -1;
        }

        int left = 0;
        int right = len - 1;
        while (left < right) {
            int mid = (left + right) >>> 1;
            if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-right-interval/solution/er-fen-cha-zhao-hong-hei-shu-by-liweiwei1419/
来源:力扣(LeetCode)

import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;

public class Solution2 {

    public int[] findRightInterval(int[][] intervals) {
        int len = intervals.length;
        if (len == 0) {
            return new int[0];
        }

        TreeMap<Integer, Integer> treeMap = new TreeMap<>();
        int[] res = new int[len];
        for (int i = 0; i < len; i++) {
            treeMap.put(intervals[i][0], i);
        }
        for (int i = 0; i < len; i++) {
            Map.Entry<Integer, Integer> entry = treeMap.ceilingEntry(intervals[i][1]);
            if (entry == null) {
                res[i] = -1;
            } else {
                res[i] = entry.getValue();
            }
        }
        return res;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-right-interval/solution/er-fen-cha-zhao-hong-hei-shu-by-liweiwei1419/
来源:力扣(LeetCode)

寻找峰值(medium难度)

https://leetcode-cn.com/problems/find-peak-element/

本题方法和代码来源:
作者:guanpengchn
链接:https://leetcode-cn.com/problems/find-peak-element/solution/hua-jie-suan-fa-162-xun-zhao-feng-zhi-by-guanpengc/
来源:力扣(LeetCode)

class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0, right = nums.length - 1;
        for (; left < right; ) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[mid + 1]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

作者:guanpengchn
链接:https://leetcode-cn.com/problems/find-peak-element/solution/hua-jie-suan-fa-162-xun-zhao-feng-zhi-by-guanpengc/
来源:力扣(LeetCode)

搜索二维矩阵(medium难度)

https://leetcode-cn.com/problems/search-a-2d-matrix/

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int targetRow = binarySearch(target, matrix);
        int left = 0;
        int right = matrix[targetRow].length - 1;
        //横向二分查找找到target所在的列
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (matrix[targetRow][mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return matrix[targetRow][left] == target;
    }
    //先纵向二分查找找到target所在的行
    private int binarySearch(int target, int[][] matrix) {
        int left = 0;
        int right = matrix.length - 1;
        int column = matrix[0].length - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (matrix[mid][column] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left;
    }
}

作者:HIT_whc
链接:https://leetcode-cn.com/problems/search-a-2d-matrix/solution/javaheng-xiang-zong-xiang-liang-ci-er-fe-v5v0/
来源:力扣(LeetCode)

搜索二维矩阵Ⅱ(medium难度)

https://leetcode-cn.com/problems/search-a-2d-matrix-ii/

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/solution/er-fen-fa-pai-chu-fa-python-dai-ma-java-dai-ma-by-/
来源:力扣(LeetCode)

public class Solution {

    public boolean searchMatrix(int[][] matrix, int target) {
        int rows = matrix.length;
        if (rows == 0) {
            return false;
        }
        int cols = matrix[0].length;
        if (cols == 0) {
            return false;
        }


        // 起点:左下角
        int x = rows - 1;
        int y = 0;
        // 不越界的条件是:行大于等于 0,列小于等于 cols - 1
        while (x >= 0 && y < cols) {
            // 打开注释,可以用于调试的代码
            // System.out.println("沿途走过的数字:" + matrix[x][y]);
            if (matrix[x][y] > target) {
                x--;
            } else if (matrix[x][y] < target) {
                y++;
            } else {
                return true;
            }
        }
        return false;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/solution/er-fen-fa-pai-chu-fa-python-dai-ma-java-dai-ma-by-/
来源:力扣(LeetCode)

public class Solution {


    public boolean searchMatrix(int[][] matrix, int target) {
        // 特判
        int rows = matrix.length;
        if (rows == 0) {
            return false;
        }
        int cols = matrix[0].length;
        if (cols == 0) {
            return false;
        }

        // 起点:右上角
        int x = 0;
        int y = cols - 1;

        // 不越界的条件是:行小于等于 rows - 1,列大于等于 0
        while (x < rows && y >= 0) {
            // 打开注释,可以用于调试的代码
            // System.out.println("沿途走过的数字:" + matrix[x][y]);
            if (matrix[x][y] > target) {
                y--;
            } else if (matrix[x][y] < target) {
                x++;
            } else {
                return true;
            }
        }
        return false;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/solution/er-fen-fa-pai-chu-fa-python-dai-ma-java-dai-ma-by-/
来源:力扣(LeetCode)

class Solution {
    private int diagonalBinarySearch(int[][] matrix, int diagonal, int target) {
        int left = 0;
        int right = diagonal;
        while (left < right) {
            int mid = (left + right) >>> 1;
            if (matrix[mid][mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left;
    }
    // 下面两个二分查找没有使用模板,因为只是找一个数,而不是找这个数的边界
    // 用教科书上的二分查找法更简单
    private boolean rowBinarySearch(int[][] matrix, int begin, int cols, int target) {
        int left = begin;
        int right = cols;

        while (left <= right) {
            int mid = (left + right) >>> 1;
            if (matrix[begin][mid] == target) {
                return true;
            } else if (matrix[begin][mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return false;
    }

    private boolean colBinarySearch(int[][] matrix, int begin, int rows, int target) {
        // 这里可以 + 1
        int left = begin + 1;
        int right = rows;

        while (left <= right) {
            int mid = (left + right) >>> 1;
            if (matrix[mid][begin] == target) {
                return true;
            } else if (matrix[mid][begin] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return false;
    }

    public boolean searchMatrix(int[][] matrix, int target) {
        // 特判
        int rows = matrix.length;
        int cols = matrix[0].length;
        int minVal = Math.min(rows, cols);
        // 沿着对角线搜索第 1 个大于等于 target 的数的索引
        int index = diagonalBinarySearch(matrix, minVal - 1, target);
        if (matrix[index][index] == target) {
            return true;
        }
        // 沿着对角线朝两边搜索
        for (int i = 0; i <= index; i++) {
            // 行搜索传入列总数 - 1
            boolean rowSearch = rowBinarySearch(matrix, i, cols - 1, target);// 列搜索传入行总数 - 1
            boolean colSearch = colBinarySearch(matrix, i, rows - 1, target);

            if (rowSearch || colSearch) {
                return true;
            }
        }
        return false;
    }
}

分割数组的最大值(hard难度)

https://leetcode-cn.com/problems/split-array-largest-sum/

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/split-array-largest-sum/solution/er-fen-cha-zhao-by-liweiwei1419-4/
来源:力扣(LeetCode)

public class Solution {

    public int splitArray(int[] nums, int m) {
        int max = 0;
        int sum = 0;

        // 计算「子数组各自的和的最大值」的上下界
        for (int num : nums) {
            max = Math.max(max, num);
            sum += num;
        }

        // 使用「二分查找」确定一个恰当的「子数组各自的和的最大值」,
        // 使得它对应的「子数组的分割数」恰好等于 m
        int left = max;
        int right = sum;
        while (left < right) {
            int mid = left + (right - left) / 2;

            int splits = split(nums, mid);
            if (splits > m) {
                // 如果分割数太多,说明「子数组各自的和的最大值」太小,此时需要将「子数组各自的和的最大值」调大
                // 下一轮搜索的区间是 [mid + 1, right]
                left = mid + 1;
            } else {
                // 下一轮搜索的区间是上一轮的反面区间 [left, mid]
                right = mid;
            }
        }
        return left;
    }

    /***
     *
     * @param nums 原始数组
     * @param maxIntervalSum 子数组各自的和的最大值
     * @return 满足不超过「子数组各自的和的最大值」的分割数
     */
    private int split(int[] nums, int maxIntervalSum) {
        // 至少是一个分割
        int splits = 1;
        // 当前区间的和
        int curIntervalSum = 0;
        for (int num : nums) {
            // 尝试加上当前遍历的这个数,如果加上去超过了「子数组各自的和的最大值」,就不加这个数,另起炉灶
            if (curIntervalSum + num > maxIntervalSum) {
                curIntervalSum = 0;
                splits++;
            }
            curIntervalSum += num;
        }
        return splits;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/split-array-largest-sum/solution/er-fen-cha-zhao-by-liweiwei1419-4/
来源:力扣(LeetCode)

寻找两个正序数组的中位数

 

代码:

public class Solution {

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
        }

        int m = nums1.length;
        int n = nums2.length;

        // 分割线左边的所有元素需要满足的个数 m + (n - m + 1) / 2;
        int totalLeft = (m + n + 1) / 2;

        // 在 nums1 的区间 [0, m] 里查找恰当的分割线,
        // 使得 nums1[i - 1] <= nums2[j] && nums2[j - 1] <= nums1[i]
        int left = 0;
        int right = m;

        while (left < right) {
            int i = left + (right - left + 1) / 2;
            int j = totalLeft - i;
            if (nums1[i - 1] > nums2[j]) {
                // 下一轮搜索的区间 [left, i - 1]
                right = i - 1;
            } else {
                // 下一轮搜索的区间 [i, right]
                left = i;
            }
        }

        int i = left;
        int j = totalLeft - i;

        int nums1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];
        int nums1RightMin = i == m ? Integer.MAX_VALUE : nums1[i];
        int nums2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];
        int nums2RightMin = j == n ? Integer.MAX_VALUE : nums2[j];

        if (((m + n) % 2) == 1) {
            return Math.max(nums1LeftMax, nums2LeftMax);
        } else {
            return (double) ((Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin))) / 2;
        }
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/he-bing-yi-hou-zhao-gui-bing-guo-cheng-zhong-zhao-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值