二进制搜索,用于在旋转的排序列表中查找旋转点
2022-09-02 22:59:21
我有一个旋转的排序列表,并希望在该列表上进行二进制搜索以查找最小元素。
假设初始列表是 {1,2,3,4,5,6,7,8} 旋转列表可以像 {5,6,7,8,1,2,3,4}
在这种情况下,正常的二进制搜索不起作用。任何想法如何做到这一点。
-- 编辑
我有彼此的条件。如果列表未排序怎么办??
我有一个旋转的排序列表,并希望在该列表上进行二进制搜索以查找最小元素。
假设初始列表是 {1,2,3,4,5,6,7,8} 旋转列表可以像 {5,6,7,8,1,2,3,4}
在这种情况下,正常的二进制搜索不起作用。任何想法如何做到这一点。
-- 编辑
我有彼此的条件。如果列表未排序怎么办??
对二进制搜索算法进行轻微修改即可;这是完全可运行的Java的解决方案(参见Serg对Delphi实现的答案,以及tkr的答案,用于算法的可视化解释)。
import java.util.*;
public class BinarySearch {
static int findMinimum(Integer[] arr) {
int low = 0;
int high = arr.length - 1;
while (arr[low] > arr[high]) {
int mid = (low + high) >>> 1;
if (arr[mid] > arr[high]) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
}
public static void main(String[] args) {
Integer[] arr = { 1, 2, 3, 4, 5, 6, 7 };
// must be in sorted order, allowing rotation, and contain no duplicates
for (int i = 0; i < arr.length; i++) {
System.out.print(Arrays.toString(arr));
int minIndex = findMinimum(arr);
System.out.println(" Min is " + arr[minIndex] + " at " + minIndex);
Collections.rotate(Arrays.asList(arr), 1);
}
}
}
这打印:
[1, 2, 3, 4, 5, 6, 7] Min is 1 at 0
[7, 1, 2, 3, 4, 5, 6] Min is 1 at 1
[6, 7, 1, 2, 3, 4, 5] Min is 1 at 2
[5, 6, 7, 1, 2, 3, 4] Min is 1 at 3
[4, 5, 6, 7, 1, 2, 3] Min is 1 at 4
[3, 4, 5, 6, 7, 1, 2] Min is 1 at 5
[2, 3, 4, 5, 6, 7, 1] Min is 1 at 6
Integer[]
int[]
>>> 1
/ 2
请注意,重复项使得 在 中无法执行此操作。考虑以下由许多和一个组成的位数组:O(log N)
1
0
(sorted)
01111111111111111111111111111111111111111111111111111111111111111
^
(rotated)
11111111111111111111111111111111111111111111101111111111111111111
^
(rotated)
11111111111111101111111111111111111111111111111111111111111111111
^
这个数组可以以某种方式旋转,并且不可能找到in,因为没有办法判断它是在“中间”的左侧还是右侧。N
0
O(log N)
我有彼此的条件。如果列表未排序怎么办??
然后,除非您想先对其进行排序并从那里继续,否则您必须进行线性搜索才能找到最小值。
下图说明了建议的算法: