LeetCode——二分查找(Java)

二分查找

  • 简介
  • 704.二分查找
  • [35. 搜索插入位置](#35. 搜索插入位置)
  • [34. 在排序数组中查找元素的第一个和最后一个位置](#34. 在排序数组中查找元素的第一个和最后一个位置)

简介

记录一下自己刷题的历程以及代码,会尽量把在本地测试包含main函数的完整代码贴上,以及一些注释掉的输出语句。写题过程中参考了 代码随想录。会附上一些个人的思路,如果有错误,可以在评论区提醒一下。

704.二分查找

原题链接
right = nums.length - 1;是一种闭区间的写法,左右下标都在数组范围内,此时while循环中需要加上=,否则会在nums = [5],target = 5的情况下报错。

java 复制代码
class Solution {
    public int search(int[] nums, int target){
        if(target<nums[0] || target>nums[nums.length-1]){
            return -1;
        }
        int left = 0;
        int right = nums.length - 1;
        int mid = 0;
        while(left <= right){
            //System.out.println("left:" + left + "  mid:" + mid + "  right:" + right);
            mid = (left + right) / 2;
            if(target > nums[mid]) {
                left = mid + 1;
            }else if(target < nums[mid]){
                right = mid - 1;
            }else{
                return mid;
            }
        }
        return -1;
    }
}

public class main {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{-1,0,3,5,9,12};
        int target = 9;
        System.out.println(solution.search(nums,target));
    }
}

35. 搜索插入位置

原题链接

总共四种情况

①找到元素,返回middle

找不到元素,循环正常退出,此时有right = left-1

②在所有元素之前,此时left = 0;right = -1 target需要插入0,即left的位置

③在两个元素中间,此时nums[left]>target;nums[right]<targettarget需要插入left的位置

④在所有元素之后,此时right=nums.length()-1;left=nums.length()target需要插入left的位置

java 复制代码
class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int mid = 0;
        while(left <= right){
            mid = (left + right) / 2;
            //System.out.println("left:" + left + "  mid:" + mid + "  right:" + right);
            if(target > nums[mid]) {
                left = mid + 1;
            }else if(target < nums[mid]){
                right = mid - 1;
            }else{
                return mid;
            }
        }
        return left;
    }
}

public class main {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{1,3};
        int target = 0;
        System.out.println(solution.searchInsert(nums,target));
    }
}

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

原题链接

方法一:找到nums[mid] == target时在mid左右继续查找相等的值,在二分查找的代码上增加一些功能即可,但是当连续的数字过多时容易将复杂度退到O(n),相当于遍历的复杂度。可以通过这道题,但是时间复杂度较高。

方法二:分别寻找左右边界,左边界指向 该元素第一个位置之前的元素,右边界指向最后一个位置之后的元素。

例如找左边界:nums[mid] == target时也要把范围划到mid左边,因为我们需要找的是target的边界

java 复制代码
int left = 0;
int right = nums.length - 1;
int leftBorder = -2;
while(left <= right){
    if(target > nums[mid]) {
        left = mid + 1;
    }else if(target < nums[mid]){
        right = mid - 1;
        leftBorder = right;
    }else if(target == nums[mid]){
        right = mid - 1;
        leftBorder = right;
    }
}

查找左右边界的函数内部的判断语句是由上面的判断语句三种情况合并而成,结果如下:

java 复制代码
class Solution {
    public int[] searchRange(int[] nums, int target) {
        int leftBorder = searchLeft(nums, target);
        int rightBorder = searchRight(nums, target);
        if(leftBorder == -2 || rightBorder == -2) return new int[]{-1 ,-1};
        if(rightBorder - leftBorder > 1) return new int[]{leftBorder + 1,rightBorder - 1};
        return new int[]{-1 ,-1};
    }

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

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


}

public class main {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = new int[]{2, 2};
        int target = 3;
        int[] array = solution.searchRange(nums,target);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
    }
}
相关推荐
弗拉唐23 分钟前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi771 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3431 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀1 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
哭泣的眼泪4081 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
清炒孔心菜1 小时前
每日一题 LCR 078. 合并 K 个升序链表
leetcode
蓝黑20202 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea
Ysjt | 深2 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
shuangrenlong2 小时前
slice介绍slice查看器
java·ubuntu