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] + " ");
        }
    }
}
相关推荐
程序媛学姐6 分钟前
SpringKafka错误处理:重试机制与死信队列
java·开发语言·spring·kafka
奋进的小暄15 分钟前
贪心算法(15)(java)用最小的箭引爆气球
算法·贪心算法
向阳25623 分钟前
SpringBoot+vue前后端分离整合sa-token(无cookie登录态 & 详细的登录流程)
java·vue.js·spring boot·后端·sa-token·springboot·登录流程
Scc_hy28 分钟前
强化学习_Paper_1988_Learning to predict by the methods of temporal differences
人工智能·深度学习·算法
巷北夜未央29 分钟前
Python每日一题(14)
开发语言·python·算法
javaisC31 分钟前
c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)
c语言·算法·深度优先
爱爬山的老虎31 分钟前
【面试经典150题】LeetCode121·买卖股票最佳时机
数据结构·算法·leetcode·面试·职场和发展
SWHL32 分钟前
rapidocr 2.x系列正式发布
算法
XiaoLeisj40 分钟前
【MyBatis】深入解析 MyBatis XML 开发:增删改查操作和方法命名规范、@Param 重命名参数、XML 返回自增主键方法
xml·java·数据库·spring boot·sql·intellij-idea·mybatis
风象南41 分钟前
SpringBoot实现数据库读写分离的3种方案
java·spring boot·后端