leetcode33 34 35 81——二分法查找

这篇博客主要讨论了三种与排序数组相关的问题:搜索旋转排序数组、查找元素的第一个和最后一个位置以及搜索插入位置。针对每种问题,提供了详细的解决方案,包括二分查找法的应用和特殊情况的处理。通过这些算法,可以有效地在不同情况的排序数组中找到目标元素或确定插入位置。
摘要由CSDN通过智能技术生成

33、搜索旋转排序数组

class Solution {
    public int search(int[] nums, int target) {
        if(nums==null) return -1;
        if(nums[0]==target) return 0;
        if(nums[nums.length-1]==target) return nums.length-1;
        
        int l=0;
        int r=nums.length-1;

        while(l<=r){
            int mid=(l+r)/2;

            if(nums[mid]==target) return mid;
            if(nums[l]==target) return l;
            if(nums[r]==target) return r;

            
            if(nums[0] < nums[mid]){
                if(nums[0]<=target&& target<nums[mid]){
                    //0到mid 有序 且target在范围中
                    r=mid-1;
                }else{
                    //有序 但 target不在范围中
                    l=mid+1;
                }
            }else{
                //0 到mid  无序 那么 另外一半 mid到r肯定有序
                if(nums[mid]<target&& target<=nums[r]){
                    l=mid+1;
                }else{
                    r=mid-1;
                }
            }

        }

        return -1;
    }
}

分组之后 一定以某以结点 分为有序和无序

那么通过二分法查找之后,肯定是一半有序 一半无序,无序那一半还可以通过继续二分法进行查找

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

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] out=new int[2];
        out[0]=-1;
        out[1]=-1;
        if(nums==null) return out;
        /*if(nums.length==1){
            if(nums[0]==target){
                out[0]=0;
                out[1]=0;
                return out;
            }else{
                return out;
            }
        }*/
        /*if(nums.length==1&&nums[0]==target){
            out[0]=0;
            out[1]=0;
            return out;
        }*/

        //升序
        int left=0;
        int right=nums.length-1;
        int mid=0;
        int temL=0;
        int temR=0;
        while(left<=right){
            mid=(left+right)/2;

            if(nums[mid]==target){
                //向左寻找第一个  向右寻找最后一个
                temL=mid;
                while(0<=temL&&nums[temL]==target){
                    --temL;
                }
                out[0]=temL+1;

                temR=mid;
                while(temR<nums.length&&nums[temR]==target){
                    ++temR;
                }
                out[1]=temR-1;
            }

            if(nums[mid]<target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }

        return out;
    }
}

二分法查找原理

35搜索插入位置

这题解答一直没做全

个人的:

class Solution {
    public int searchInsert(int[] nums, int target) {
        if(nums==null) return 0;
        if(target<=nums[0]) return 0;
        if(target>nums[nums.length-1]) return nums.length;
        if(nums.length==1){
            if(target<=nums[0]) return 0;
            if(target>nums[nums.length-1]) return nums.length;
        }
        int mid=0;
        int left=0;
        int right=nums.length-1;

        while(left<right){
            mid=(left+right)/2;

            if(nums[mid]==target){
                return mid;
            }

            if(nums[mid]<target) {//在mid 和right之间
                left=mid+1;
                if(nums[left]>target){//mid<target<left
                    return left;
                }
            }else if(nums[mid]>target) {//有可能 在mid和left或者right之间。
                right=mid-1;
                if(nums[right]<target){//在right<target<mid之间
                    return mid;
                }
            }
        }

        return 0;
    }
}

官方:

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

 81,搜索旋转排序数组II

class Solution {
    public boolean search(int[] nums, int target) {
        //原本升序    
        //翻转之后以target为界升序
        //可能会有重复项
        if(nums==null) return false;
        if(nums.length==1 && nums[0]==target) return true;

        int left=0;
        int right=nums.length-1;
        int mid=0;

        while(left<=right){
           // mid=(nums[left] + nums[right])/2;
           //去重处理
           while(left<right && nums[left]==nums[left+1]) left++;
           while(left<right && nums[right]==nums[right-1]) right--;

            mid=(left+right)/2;
            if(nums[mid]==target) return true;
            if(nums[left]==target) return true;
            if(nums[right]==target) return true;

            //判断左半部分是否有序
            if(nums[left]<nums[mid]){
                //左半部分有序
                if(nums[left] <target && target <nums[mid]){
                     right=mid-1;
                }else{
                    left=mid+1;
                }//目标值在左半部分(有序)
                
            }else{
                //右半部分有序
                if(nums[mid] < target && target <nums[right]){
                     left=mid+1;
                }else{
                     right=mid-1;
                }

            }

            

            /*else{
                //右半部分有序
                if(nums[mid] < target && target <nums[right]) left=mid+1;
                if(nums[mid] < target) right=mid-1;
            }*/
        }
        return false;

    }
}
//重复的话  一部分有序的 可能都是一样的值 说明  相等也可能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值