Search in Rotated Sorted Array

Suppose a sorted array 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.

二分法

思路

因为rotate的缘故,当我们切取一半的时候可能会出现误区,所以我们要做进一步的判断。假设数组是A,每次左边缘为l,右边缘为r,还有中间位置是m。在每次迭代中,分三种情况:

  1. A[m] = target 找到target

  2. A[m] > A[l] 说明left 到中间是有序的, 那么就要判断target是否在l与m之间, 如果在的话则把m设为right边界, 否则的话target就在另外的一半, 把m设为left边界

  3. 如果A[m] < A[l], 说明m到r是有序的, 那么就判断target是不是在m到r之间.
    如果target在的话把m设为左边界, 否则把m设为右边界

复杂度

时间O(logn) 空间O(1)

代码

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

Search in Rotated Sorted Array II

二分法

说明

原来我们是依靠中间和边缘元素的大小关系,来判断哪一半是不受rotate影响,仍然有序的。而现在因为重复的出现,如果我们遇到中间和边缘相等的情况,我们就丢失了哪边有序的信息,因为哪边都有可能是有序的结果。假设原数组是{1,2,3,3,3,3,3},那么旋转之后有可能{3,1,2,3,3,3,3},这样的我们判断左边缘和中心的时候都是3,如果我们要寻找1或者2,我们并不知道应该跳向哪一半。解决的办法只能是对边缘移动一步,直到边缘和中间不在相等或者相遇,这就导致了会有不能切去一半的可能。

复杂度

时间 最坏情况O(n) 空间 O(1)

代码

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

lpy1990
26 声望10 粉丝