【LeetCode】解题33:Search in Rotated Sorted Array

Problem 33: Search in Rotated Sorted Array [Medium]

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm’s runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

来源:LeetCode

解题思路

  • 基本思路是利用二分查找,每层递归排除掉一半的数值。
  • 难点在于条件判断,需要考虑要查找的target会不会因为排序数组的旋转而不在原本二分查找的那半段范围。为了方便说明,将头尾相接处称为断崖,二分点下标称为p,以下为需要分类讨论的情况:
    a. 假设nums[p] < target,说明目标值较大,正常情况下需要查找数组的右半部分,此时应有nums[right] > target,需要查找p+1 ~ right-1
    b. 当nums[right] < target时,与正常情况不同,是需要讨论的重点。按断崖所在的位置进行分类讨论。
    b1. 寻找断崖所处位置的方法是比较nums[right]nums[p]的值,如果nums[right] < nums[p],则说明断崖p ~ right之间,即最大的尾部处于这之间,要找的目标值比nums[p]大,就可以在p+1 ~ right-1之间查找。(例如在[4,5,6,7,8,9,1,2,3]中寻找9的第一次二分查找。)
    b2. 如果nums[right] > nums[p],则说明p ~ right之间是严格升序的,断崖应该在left ~ p之间,因此既比nums[p]大又比nums[right]大的目标值就应该在left ~ p-1之间查找。(例如在[7,8,9,1,2,3,4,5,6]中寻找9的第一次二分查找。)
    c. 上述数值比较过程中如果有正好相等的情况则之间返回下标即可。如果有left > right的情况则说明查找失败,返回-1。
  • 数组个数为0或仅剩1个数且不为target时直接返回-1。

二分查找时间复杂度O(log n)。

要点:二分查找条件判断

Solution (Java)

class Solution {
    public int search(int[] nums, int target) {
        int N = nums.length;
        if(N == 0) return -1;
        return partSearch(nums, 0, N-1, target);
    }
    private int partSearch(int[] nums, int left, int right, int target){
        if(left > right) return -1;
        if(left == right && nums[left] != target) return -1;
        int len = right - left + 1;
        int p = left + len/2;
        if(nums[p] == target){
            return p;
        }
        else if(nums[p] < target){
            if(nums[right] == target){
                return right;
            }
            else if(nums[right] > target){
                return partSearch(nums, p+1, right-1, target);
            }
            else{
                if(nums[right] < nums[p]){
                	// 断崖在p~right之间
                    return partSearch(nums, p+1, right-1, target);
                }
                else{
                	// 断崖在另半部分
                    return partSearch(nums, left, p-1, target);
                }
            }
        }
        else{
            if(nums[left] == target){
                return left;
            }
            else if(nums[left] < target){
                return partSearch(nums, left+1, p-1, target);
            }
            else{
                if(nums[left] > nums[p]){
                	// 断崖在left~p之间
                    return partSearch(nums, left+1, p-1, target);
                }
                else{
                	// 断崖在另半部分
                    return partSearch(nums, p+1, right, target);
                }
            }
        }
    }
}

修改过程

  • 在碰到b情况时,想当然觉得断崖在另半部分,直接去搜索了另半部分,因此输入[7,8,1,2,3,4,5,6],2时,应该返回3,却错误地返回了-1。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值