Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 旋转数组的一个新变体,如何使用二进制搜索获得旋转后第一个最小元素的索引?_Arrays_Algorithm_Sorting_Data Structures_Binary Search - Fatal编程技术网

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

Arrays 旋转数组的一个新变体,如何使用二进制搜索获得旋转后第一个最小元素的索引?,arrays,algorithm,sorting,data-structures,binary-search,Arrays,Algorithm,Sorting,Data Structures,Binary Search,假设按升序排序的长度为n的数组在1到n次之间旋转。例如,数组nums=[0,1,4,4,5,6,7]可能会变成: [4,5,6,7,0,1,4]如果旋转4次。 [0,1,4,4,5,6,7]如果旋转7次。 请注意,将数组[a[0]、a[1]、a[2]、…、a[n-1]]旋转1次会导致数组[a[n-1]、a[0]、a[1]、a[2]、…、a[n-2]] 给定可能包含重复项的已排序旋转数组nums,返回旋转后该数组第一个最小元素的索引(与旋转次数相同) 例如: Input [1, 2, 3, 3,

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

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

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

例如:

Input [1, 2, 3, 3, 4, 4] Output: 0  
Input [5, 6, 1, 2, 3, 4] Output: 2  
Input [2, 3, 4, 1, 1, 1, 1] Output: 3  
Input [1, 1, 1, 1, 2, 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, start, 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, 3, 4, 4], [5, 6, 1, 2, 3, 4], [2, 3, 4, 1, 1, 1, 1], [1, 1, 1, 1, 2, 1, 1]]
for input in inputs:
    print(search_recursive(input, 0, len(input)-1))
// Outputs:
// 0
// 2
// 3
// 5
复杂性不好,因为每个元素都要访问两次

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

def search_recursive(array, start_value, end_value, start, 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, start_value, mid_value, start, mid)
    if mid_value > succ_mid_value:
        return succ_mid
    
    left = search_recursive(array, start_value, mid_value, start, mid)
    right = search_recursive(array, succ_mid_value, end_value, succ_mid, end)
    if left == 0:
        return right
    
    return min(left, right)

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

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

答案是肯定的。Google
旋转排序数组中的最小元素
您应该会看到几种解决方案。实际上这与旋转排序数组中的最小元素有点不同,对于第四个示例,我们将使用旋转排序数组中的最小元素方法得到索引为0的“1”,但是,我们想要在“2”之后加上“1”。你能提供代码吗?这很难理解。我在答案中添加了代码。如果答案对你有帮助,请接受。谢谢,有些问题。1.也许我们可以删除“if right==0:return left”,因为右边不能是0,结果可能仍然正确。2.对于第一个例子,程序似乎将运行13个递归函数,即2*len(input)+1,如果我们按顺序访问元素,可能不如N好。我添加了第二种方法。我认为这将是一个更好的搜索策略这比前一个要好。其实我也想到了一个解决办法。我们可以在旋转排序数组的最小元素中使用该方法。然后,我们通过比较第一个元素和最后一个元素来处理与第四个示例类似的特殊情况。如果它们相等,我们将从末尾访问元素,直到在“2”之后找到“1”。