leetcode雕虫小技之medium 33. Search in Rotated Sorted Array

题干: https://leetcode.com/problems/search-in-rotated-sorted-array/

 

这题要求搜索的时间复杂度在O(log(n)),很显然的一点是,如果做普通的排序数组的二分搜索,那么这个复杂度完全没问题,只不过现在有一点不同,就是那个pivot是从哪个index开始的是unknown的,这是题干所强调的。

假设这个pivot能在O(log(n))复杂度内找出来,那么剩下的就是二分搜索了,所以整体的时间复杂度就可以控制在O(log(n))内

这就是一个最直观的思路。

我这里人为定义一个pivot index如下:如果nums[k]<nums[k-1], 那么就称k为pivot index, 可以简单看出,这样的k在数组有翻转的情况下,有且仅有1个,在数组无翻转的情况下,不存在!

那么怎样在O(log(n))内找到k呢?

想想大概也知道,二分搜索嘛。不过这里面index的边界trick非常多,要十分注意,小心检查。

我这里隐约感觉我这个做法不是最直观的,应该有其他等价但看起来更优雅的代码,大家可以自己去找。

好了,上代码:

package com.example.demo.leetcode;

public class RotatedSorted {
    public int search(int[] nums, int target) {
        if(nums.length<1){
            return -1;
        }
        if(nums.length==1){
            return target==nums[0]?0:-1;
        }
        int pivot = findPivotIndex(nums, 0, nums.length-1);
        System.out.println("pivot is: "+ pivot);
        if(pivot==-1){
            // already in order
            return binarySearch(nums, 0, nums.length-1, target);
        }
        if(target<nums[0]){
            // search int the right part, pivot~nums.length-1
            return binarySearch(nums, pivot, nums.length-1, target);
        }else{
            // search in the left part 0~pivot-1
            return binarySearch(nums, 0, pivot-1, target);
        }
    }

    private int findPivotIndex(int[] nums, int startIndex, int endIndex){
        if(endIndex<=startIndex){
            //至少要有两个元素,才好做这种操作
            return -1;
        }
        if(endIndex-startIndex==1){
            if(nums[0]>nums[1]){
                return 1;
            }else{
                return -1;
            }
        }

        int leftIndex = startIndex;
        int rightIndex = endIndex;

        // find the index k that nums[k-1]>nums[k] and nums[k1+1]>nums[k]
        int midIndex = (leftIndex+rightIndex)/2;
        while(true){
            if(leftIndex>rightIndex){
                return -1;
            }
            if(midIndex>0 && nums[midIndex]<nums[midIndex-1]){
                // matched
                return midIndex;
            }
            if(nums[startIndex]<=nums[midIndex]){
                //处于左连续段,往右侧去搜吧
                leftIndex = midIndex+1;
                midIndex = (leftIndex+rightIndex)/2;
            }else{
                //处于右连续段,往左侧去搜吧,包括自己
                rightIndex = midIndex;
                midIndex = (leftIndex+rightIndex)/2;
            }
//            System.out.println("left: "+ leftIndex+",mid:"+midIndex+",right:"+rightIndex);
        }

    }


    private  int binarySearch(int[] nums, int startIndex, int endIndex, int target){
        if(startIndex>endIndex){
            return -1;
        }
        if(startIndex==endIndex){
            return nums[startIndex]==target?startIndex:-1;
        }

        int midIndex = (startIndex+endIndex)/2;
        if(target==nums[midIndex]){
            return midIndex;
        }else if(target>nums[midIndex]){
            return binarySearch(nums, midIndex+1, endIndex, target);
        }else{
            return binarySearch(nums, startIndex, midIndex-1, target);
        }
    }

    public static void main(String[] args) {
        //边界条件: nums为空
//        int[] nums = {4,5,6,7,0,1,2};
//        int[] nums = {4,5,6,7,0,1,2};
//        int[] nums = {1,3};
        int[] nums = {3,5,1};
        int target = 1;
        RotatedSorted demo = new RotatedSorted();
        int ret = demo.search(nums, target);

        System.out.println(ret);
    }
}

 

反思:这题出的不怎么好,从leetcode的test case来看,是允许存在未经旋转的排序数组的,也允许出现空数组,但是题干中都没有提到,导致我出了一些边角条件的问题,shit~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值