第四类

部分sorted的array或者rotated的array

  • search in rotated sorted array
  • search in rotated sorted array II(duplicate allowed)
  • find min in rotated sorted array
  • find min in rotated sorted array II(duplicate allowed)

虽然rorate,但是只rotate了一次,如果二分必然有一半是sorted的有一半不是。通过判断中心点和边缘,比如mid和end,就可以知道哪边有序,然后就能够知道往左右哪边走是对的。

对于有duplicate的rotated数组,比如[3,1,2,3,3,3,3],中心和边缘都是3,无法判断往哪边走,所以只能将边界start或者end移动一步,这样就可能没法切去一半,复杂度就是o(n)

注意点

  • 应该先判断是否rotated, 如果nums[0] < nums[length-1]说明没有rotate
  • 判断array的长度: 0, 1, 2

Search In Rotated Sorted Array

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        length = len(nums)
        if length == 0:
            return -1

        start, end = 0, length - 1
        while start + 1 < end:
            mid = start + (end - start) / 2
            if target == nums[mid]:
                return mid
            if nums[start] < nums[mid]:
                #left is sorted
                if nums[start] <= target and target < nums[mid]:
                    end = mid
                else:
                    start = mid
            else:
                #right is sorted
                if target > nums[mid] and target <= nums[end]:
                    start = mid
                else:
                    end = mid

        if nums[start] == target:
            return start
        if nums[end] == target:
            return end
        return -1

Search Rotated Array II

对于有duplicate的rotated数组,比如[3,1,2,3,3,3,3],中心和边缘都是3,无法判断往哪边走

会影响时间复杂度,加上下面这个判断,只能将start挪一步再判断,worst case是O(n)

因为这一题是要找到target这个值,所以我们判断哪一边是sorted的,这里我们一直采取比较left和mid的办法,如果left和Mid相等,我们就将left + 1,直到能够判断哪一边是sorted的,将这个范围与target比较,就能够知道该往那边走。

elif nums[start] == nums[mid]:
                start += 1

Find Minimum in Rotated Sorted Array

如果是sorted: nums[start] < nums[end]应该直接返回左边

class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length = len(nums)
        #length check
        if length == 0:
            return -1

        if length == 1:
            return nums[0]

        if length == 2:
            return min(nums)

        start, end = 0, length - 1

        while start + 1 < end:
            #rotate check
            if nums[start] < nums[end]:
                return nums[start]
            mid = start + (end - start) / 2
            if nums[mid] < nums[mid-1] and nums[mid] < nums[mid+1]:
                return nums[mid]
            if nums[start] < nums[mid]:
                #left is sorted
                    start = mid
            else:
                #right is sorted
                    end = mid

        if nums[start] < nums[end]:
            return nums[start]
        return nums[end]

Find Minimum in Rotated Sorted Array II

这一题不同于search in rotated sorted array ii, 因为这里不是要找一个target,而是要找minimum。

  • 如果已经sorted,直接返回左边,这个应该每次都check,因为在相等drop掉一些值时,有可能已经变成了sorted的array
class Solution(object):
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length = len(nums)
        #length check
        if length == 0:
            return -1

        if length == 1:
            return nums[0]

        if length == 2:
            return min(nums)

        start, end = 0, length - 1

        while start + 1 < end:
            #rotate check
            if nums[start] < nums[end]:
                return nums[start]
            mid = start + (end - start) / 2
            if nums[mid] < nums[mid-1] and nums[mid] < nums[mid+1]:
                return nums[mid]
            if nums[start] < nums[mid]:
                #left is sorted
                start = mid
            #add this condition
            elif nums[start] == nums[mid]:
                start += 1
            else:
                #right is sorted
                end = mid

        if nums[start] < nums[end]:
            return nums[start]
        return nums[end]