leetcode33. Search in Rotated Sorted Array相同的思路,不同的复杂度

本文详细解析了在旋转数组中使用二分搜索寻找目标值的复杂过程,包括确定旋转点、坐标转换及优化代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接
第一眼看到这个题,本能的想到二分搜索。自己的解法是这样:

  1. 先找到最小的值反转后的的位置,例如题目中的数组[4,5,6,7,0,1,2]中0在第四位,记为cur = 4,如何寻找呢?
    顺序找肯定是不可取的,但是我第一次没有转个来这个弯,居然采用顺序查找的方式(那为什么不直接顺序查找target呢?真是笨)
  2. 找到cur的位置便可以使用经典的二分查找法,但必须在翻转前后的坐标之间做一个转换,这个转换的工作在下面的代码里会有体现。
class Solution:
    def search(self, nums: 'List[int]', target: 'int') -> 'int':
        nums_L = len(nums)
        cur = 0
        for i in range(1, nums_L):
            if nums[i] < nums[i - 1]:
                cur = i
                break
	#上面求cur
        if cur != 0:
            Solution.tran_cur = Solution.tran_cur1
        elif nums[0] < nums[nums_L -1]:
            Solution.tran_cur = Solution.tran_cur2
        else:
            Solution.tran_cur = Solution.tran_cur3
        #根据cur的不同选取不同的转换函数,实际上这一步可用方法二中的一行代码就可以替换掉
        l_, r_ = (0), (nums_L - 1)
        l, r = Solution.tran_cur(l_, nums_L, cur), Solution.tran_cur(r_, nums_L, cur)

        while l_ <= r_:
            mid_ = int((l_ + r_) / 2)
            mid = Solution.tran_cur(mid_, nums_L, cur)
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                l_ = mid_ + 1
                l = Solution.tran_cur(l_, nums_L, cur)
            else:
                r_ = mid_ - 1
                r = Solution.tran_cur(r_, nums_L, cur)

        return -1
#下面是三个转换函数
    def tran_cur1(i, nums_L, cur):
        l = i - (nums_L - cur)
        r = i + cur
        if l >= 0 and l < nums_L:
            return l
        else:
            return r
    def tran_cur2(i, nums_L, cur):
        return i
    def tran_cur3(i, nums_L, cur):
        return nums_L - i -1

不得不说,我自己都觉得这代码实在太他妈的啰嗦,但精简的代码毕竟都是由繁入简一步步得到的。别看这代码啰嗦,而且计算cur时还是暴力算的,但是居然还beat了leetcode上67%的人,我感觉直接找都应该比这个方法要快!下面贴一个根据评论区某位老兄的代码改来的python版代码,思路其实相同。

class Solution:
    def search(self, nums: 'List[int]', target: 'int') -> 'int':
        nums_L = len(nums)
        lo, hi = 0, nums_L-1
#采用二分的方式来求翻转后数组中的最小值,
        while lo<hi:
            mid = int((lo+hi)/2)
            if nums[mid]>nums[hi]: lo = mid+1
            else: hi = mid
        cur = lo
        lo, hi = 0, nums_L-1
        while lo <= hi:
            mid = int((lo+hi)/2)
            #下面这行代码便是翻转前后坐标的转换,一行搞定,实在令人佩服!
            realmid = (mid+cur)%nums_L
            if nums[realmid]==target: return realmid
            elif nums[realmid]<target: lo = mid+1
            else: hi = mid-1
        return -1

这题虽然不难,但是花的时间却真不少,感触也很深。做这种题目一般都是通过一个具体的实例来想一个较为通用的解法,很多时候思路对了,但是因为不能够覆盖的了所有的情况又会导致很多错误的出现,而这些错误往往会通过一些特殊的做法来解决,不仅导致代码量的增加,而且在解决的过程中,还有可能会引出其他的一些错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值