微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

旋转数组的新变体,如何使用二进制搜索获得旋转后第一个最小元素的索引?

如何解决旋转数组的新变体,如何使用二进制搜索获得旋转后第一个最小元素的索引?

假设一个按升序排序的长度为 n 的数组在 1 到 n 次之间旋转。例如,数组 nums = [0,1,4,5,6,7] 可能会变成:

[4,7,4] 如果旋转了 4 次。
[0,7] 如果旋转 7 次。
请注意,将数组 [a[0],a[1],a[2],...,a[n-1]] 旋转 1 次会导致数组 [a[n-1],a[0],a[n-2]]。

给定排序后的旋转数组nums可能包含重复,返回旋转后该数组第一个最小元素的索引(与旋转次数相同)。

例如:

Input [1,2,3,4] Output: 0  
Input [5,4] Output: 2  
Input [2,1] Output: 3  
Input [1,1] Output: 5  

我们可以使用二分搜索解决它吗?在最坏的情况下,时间复杂度为 O(n),但在一般情况下会好得多。

解决方法

如果左邻居大于当前位置值,则进行二分查找并查看每个位置。然后返回位置索引。否则返回0。

在 Python 中你可以编写

def search_recursive(array,start,end):
    if start > end:
        return 0

    mid = (start + end) // 2
    if mid > 0 and array[mid - 1] > array[mid]:
        return mid

    left = search_recursive(array,mid-1)
    right = search_recursive(array,mid+1,end)
    if left == 0:
        return right
    if right == 0:
        return left
    return min(left,right)

inputs = [[1,2,3,4,4],[5,6,1,[2,1],[1,1]]
for input in inputs:
    print(search_recursive(input,len(input)-1))
// Outputs:
// 0
// 2
// 3
// 5

复杂度不好,因为你访问每个元素两次。

另一种方法是使用二分搜索点和一些分支的切割。例如,在 [5,4] 以及值 start=5,mid=1,succ_mid=2end=4 中,您可以将搜索集中到数组 [5,1]。我的实现如下所示:

def search_recursive(array,start_value,end_value,end):
    if start >= end:
        return 0
    
    mid = (start + end) // 2
    mid_value = array[mid]
    
    succ_mid = mid + 1
    succ_mid_value = array[succ_mid]

    if start_value > mid_value:
        return search_recursive(array,mid_value,mid)
    if mid_value > succ_mid_value:
        return succ_mid
    
    left = search_recursive(array,mid)
    right = search_recursive(array,succ_mid_value,succ_mid,end)
    if left == 0:
        return right
    
    return min(left,input[0],input[len(input)-1],len(input)-1))

// Outputs:
// 0
// 2
// 3
// 5

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。