美文网首页算法学习
算法题--在旋转过的有序数组里寻找指定元素

算法题--在旋转过的有序数组里寻找指定元素

作者: 岁月如歌2020 | 来源:发表于2020-04-24 02:44 被阅读0次
image.png

0. 链接

题目链接

1. 题目

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

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

You are given a target value to search. If found in the array return true, otherwise return false.

Example 1:

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

Example 2:

Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false

Follow up:

This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates.
Would this affect the run-time complexity? How and why?

2. 思路1:二分查找变体

  • 初始化 left = 0, right = len(nums) - 1
  • 在循环每一步, 计算 mid = left + (right - left) // 2,
    • 如果target == nums[mid], 则直接返回True
    • 如果nums[mid] < nums[left], 说明mid处于右半边, 则[mid, right]区间是有序的, 如果target处于这个区间, 则只需要left = mid + 1后在这个区间继续寻找了, 否则, 可以排除target处于[mid, right]的可能性, 则right = mid - 1后在mid以左寻找
    • 如果nums[mid] > nums[left], 说明mid处于左半边, 则[left, mid]区间是有序的, 如果target处于这个区间, 则只需要right = mid - 1后在这个区间继续寻找了, 否则, 可以排除target处于[left, mid]的可能性, 则left = mid + 1后在mid以右寻找
    • 无法判断mid处于哪个半边, 只好left += 1右移继续;所以此算法最坏情况时间复杂度是O(n)

3. 代码

# coding:utf8
from typing import List


class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        if len(nums) == 0:
            return False

        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] == target:
                return True
            elif nums[mid] < nums[left]:
                # mid处于右半边, 则[mid, right]是有序的
                if nums[mid] < target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1
            elif nums[mid] > nums[left]:
                # mid处于左半边, 则[left, mid]是有序的
                if nums[left] <= target < nums[mid]:
                    right = mid - 1
                else:
                    left = mid + 1
            else:
                # mid和left元素相同, 此时无法分清mid到底处于左半边还是右半边, 只好让left往右移
                left += 1

        return False


def my_test(solution, nums, target):
    print('input: nums={}, target={}, \noutput: {}'.format(nums, target, solution.search(nums, target)))
    print('=' * 50)


solution = Solution()
my_test(solution, [2, 5, 6, 0, 0, 1, 2], 0)
my_test(solution, [2, 5, 6, 0, 0, 1, 2], 3)
my_test(solution, [], 5)
my_test(solution, [1, 3], 3)
my_test(solution, [1, 1, 3], 3)
my_test(solution, [1, 1, 5], 1)
my_test(solution, [1, 3, 1, 1, 1], 3)

输出结果

input: nums=[2, 5, 6, 0, 0, 1, 2], target=0, 
output: True
==================================================
input: nums=[2, 5, 6, 0, 0, 1, 2], target=3, 
output: False
==================================================
input: nums=[], target=5, 
output: False
==================================================
input: nums=[1, 3], target=3, 
output: True
==================================================
input: nums=[1, 1, 3], target=3, 
output: True
==================================================
input: nums=[1, 1, 5], target=1, 
output: True
==================================================
input: nums=[1, 3, 1, 1, 1], target=3, 
output: True
==================================================

4. 结果

image.png

相关文章

网友评论

    本文标题:算法题--在旋转过的有序数组里寻找指定元素

    本文链接:https://www.haomeiwen.com/subject/spitwhtx.html