leetcode 双调查找相关题目

出处

《算法》1.4.20
33. 搜索旋转排序数组 https://leetcode-cn.com/problems/search-in-rotated-sorted-array/
81. 搜索旋转排序数组 II https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/
153. 寻找旋转排序数组中的最小值 https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/
154. 寻找旋转排序数组中的最小值 II https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/

都是衍生的相似题目,33题对应《算法》上面的1.4.20

算法上的题目

在这里插入图片描述
https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/ 852. 山脉数组的峰顶索引这一题很像,可以参考之前写的答案:https://blog.csdn.net/hhmy77/article/details/108193937

33. 搜索旋转排序数组

1 暴力

暴力法很容易写出,但是算法级别是 O ( N ) O(N) O(N),不符合题意

class Solution {
    public int search(int[] nums, int target) {
        if(nums==null){
            return -1;
        }
        for(int i=0;i<nums.length;i++){
            if(nums[i]==target){
                return i;
            }
        }
        return -1;
    }
}

2 二分

原数组不是递增的,但是是通过递增数组旋转回来的,如果能找到这个旋转的点,将数组旋转成递增数组,那么就能使用二分了

或者我们再找到这个数组的分界点的时候,分别对左右两个部分做二分,然后判断target在不在这两个部分里面也行

但是编写代码的过程中发现直接二分找peak似乎不太好找,所以先用 O ( N ) O(N) O(N)算法来找peak,然后再对两个部分进行二分搜索,下面代码是AC的
时间复杂度由于有一个 O ( N ) O(N) O(N)级别的算法,所以下面做法不是最优的

class Solution {
    public int search(int[] nums, int target) {
        // 特殊判断
        if(nums.length==1){
            if(nums[0]==target)
                return 0;
            else
                return -1;
        }
        int peak = findPeak(nums);
        int left=b_search(nums,0,peak,target);
        int right=b_search(nums,peak+1,nums.length-1,target);
        // System.out.println(peak+" "+left+" "+right);
        if(left!=-1)
            return left;
        if(right!=-1)
            return right;
        return -1;
    }

    public int findPeak(int[] nums){
        int i=0;
        for(;i<nums.length-1;i++){
            if(nums[i]>nums[i+1])
                break;
        }
        return i;
    }
    
    public int b_search(int[] nums,int lo,int hi,int target){
        while(lo<=hi){
            int mid=(lo+hi)/2;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]>target){
                hi=mid-1;
            }else{
                lo=mid+1;
            }
        }
        return -1;
    }
}

接下来尝试写出用二分来findPeak,但是这里我还不会做,不能直接照搬山脉数组的写法,因为这题里面会有两个peak,而我们需要找的是最大的那个peak,所以如果我们直接二分的话,只会找到一个peak,它可能是最大值,也可能不是,只有用最大值的peak来划分,接下来才能得到正确的二分结果,可能需要递归来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值