力扣刷题Day 71:搜索旋转排序数组(33)

1.题目描述

2.思路

方法1(自己想的):首先用分治法找到数组前半段和后半段的衔接处separate,若target刚好在nums[: separate]或nums[separate + 1 :]里则在对应区间里二分查找target,否则直接返回-1。

方法2(受灵茶山艾府佬题解的启发):不停二分,判断nums[mid]与nums末尾元素的大小关系,如果nums[mid] < nums[-1],那么分割点separate一定在[left, mid - 1]上,否则分割点separate就在[mid + 1, right]上,找到separate之后就和方法1一样,若target刚好在nums[: separate]或nums[separate + 1 :]里则在对应区间里二分查找target,否则直接返回-1。

3.代码(Python3)

方法1:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        def search_separate(left, right):
            if left > right: return -1
            elif left == right and nums[left] == target: return left
            mid = (left + right) // 2
            if mid + 1 == len(nums): return -1
            if nums[mid] > nums[mid + 1]: return mid
            separate = search_separate(left, mid - 1)
            if separate == -1: separate = search_separate(mid + 1, right)
            return separate
        
        separate = search_separate(0, len(nums) - 1)
        if separate == -1: separate = len(nums) - 1 # nums没有旋转的情况
        elif nums[separate] == target: return separate
        elif target < nums[separate + 1] or target > nums[separate]: return -1
        
        left, right = 0, separate
        if separate != len(nums) - 1 and target <= nums[-1]: left, right = separate + 1, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == target: return mid
            elif nums[mid] > target: right = mid - 1
            else: left = mid + 1
        return -1

方法2:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] < nums[-1]: right = mid - 1
            elif nums[mid] > nums[-1]: left = left + 1
            else: break
            
        separate = left - 1
        if left == 0: separate = len(nums) - 1 # nums没有旋转的情况
        elif target < nums[separate + 1] or target > nums[separate]: return -1
        
        left, right = 0, separate
        if separate != len(nums) - 1 and target <= nums[-1]: left, right = separate + 1, len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == target: return mid
            elif nums[mid] > target: right = mid - 1
            else: left = mid + 1
        return -1

4.执行情况

方法1:

方法2:

5.感想

我写的方法虽然执行效果还可以,但代码可读性极差,是在一次一次通不过测试用例的过程中不断修补的,所以看起来非常东拼西凑,差评!灵茶山艾府佬的题解思想非常妙,但是应用在我的代码里效率反而没那么高,不知道为什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值