二分查找三道题

文章介绍了二分查找算法的两种常见实现方式——左闭右闭和左闭右开,分析了它们的区别,包括right的起始位置、比较条件以及边界更新。此外,还讨论了在处理有重复元素时如何调整二分查找以找到第一个出现的元素,并提供了一个解决方案。最后,文章给出了一个LeetCode问题540,要求在有序数组中找到唯一出现一次的元素,再次利用二分查找的思想,确保了O(logn)的时间复杂度。
摘要由CSDN通过智能技术生成
  1. 二分查找
    两种写法:左闭右闭[left,right]、左闭右开[left,right)
    主要有几点不同:1. right是从num.length开始还是从num.length-1开始。2.left<=还是<right。3.right=mid还是mid+1

左闭右闭写法:


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

左闭右开写法:

    public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length;
        while(left<right){
            int mid=(left+right)/2;
            if(nums[mid]<target){
                left=mid+1;
            }else if(nums[mid]>target){
                right=mid;
            } else{
                return mid;
            }
        }
        return -1;
    }
  1. 有重复元素的二分查找,返回重复元素的第一个位置。输入{1,2,3,3,3,3,4,5}和3,返回2
    public static void main(String[] args) {
        search(new int[]{1,2,3,3,3,3,4,5},3);
    }
    public static int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (target > nums[mid]) {

                left = mid + 1;
            } else if (target < nums[mid]) {
                right = mid - 1;
            } else {
                while(mid>0&&nums[mid]==nums[mid-1]){
                    mid--;
                }
                return mid;
            }
        }
        return -1;
    }
  1. leetcode540. 有序数组中的单一元素
    题目描述:给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。 请你找出并返回只出现一次的那个数。
    你设计的解决方案必须满足 o(log n) 时间复杂度和 (1)空间复杂度。

示例:
输入:nums=[1,1,2,3,3,4,4,8,8]
输出:2
输入:nums=[3,3,7,7,10,11,11]
输出:10

一般是偶数位和它后面的奇数位的数值相同。如:11223344
一旦只出现一次元素,那么就变成奇数位和后面的偶数位数值相同了。如:1123344

  1. while循环终止的时候是left=right。退出的时候返回nums[left]和nums[right]都可以。
    public int singleNonDuplicate(int[] nums) {
        //
        int left=0;
        int right=nums.length-1;//这里不减一 会报数组越界的错
        while(left<right){    //左闭右开写法
            int mid=(left+right)/2;
            if(mid%2==0){
                if(nums[mid]==nums[mid+1]){
                    left=mid+1;
                } else{
                    right=mid;
                }
            } else{
                if(nums[mid]==nums[mid+1]){
                    right=mid;
                } else{
                    left=mid+1;
                }
            }
        }
        return nums[left];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值