我有一个Sorted数组。我们假设
{4,7,9,12,23,34,56,78}
给定min和max我想以有效的方式在min和max之间找到数组中的元素。
Cases:min=23 and max is 78 op:{23,34,56,78}
min =10 max is 65 op:{12,23,34,56}
min 0 and max is 100 op:{4,7,9,12,23,34,56,78}
Min 30 max= 300:{34,56,78}
Min =100 max=300 :{} //empty
我想找到有效的方法来做到这一点?我不是要求代码我可以在这里使用任何算法,如DP指数搜索?
答案 0 :(得分:3)
由于它已经排序,您可以通过在整个数组上使用二进制搜索,轻松找到大于或等于所需最小值的最低元素。
二进制搜索在每次迭代时基本上将serch空间减少一半。给出10
的第一个示例,您可以使用12
上的中点开始如下:
0 1 2 3 4 5 6 7 <- index
4 7 9 12 23 34 56 78
^^
由于您正在查看的元素高于10而下一个元素较低,因此您已找到它。
然后,您可以使用类似的二进制搜索,但只能使用您刚刚找到的元素的那一部分。这次你正在寻找小于或等于所需最大值的最高元素。
在前面提到的相同示例中,您从:
开始 3 4 5 6 7 <- index
12 23 34 56 78
^^
由于它小于65而且以下也是,你需要将指针增加到34..78
的中间点:
3 4 5 6 7 <- index
12 23 34 56 78
^^
而且你有它,因为这个数字较少而且以下数字更多(超过65)
然后你可以从停止索引(3和6)开始提取值。
0 1 2 3 4 5 6 7 <- index
4 7 9 ((12 23 34 56)) 78
-----------
算法的时间复杂度为O(log N)
。但请记住,这在处理更大的数据集时才变得非常重要。如果你的数据集只包含大约8个元素,你也可以使用线性搜索,因为(1)它更容易编写; (2)时差与无关。
我倾向于不担心时间复杂性,除非操作非常昂贵,数据集大小达到数千,或者我不得不每秒进行数千次。
答案 1 :(得分:2)
因为它已经排序,所以应该这样做:
List<Integer> subarray = new ArrayList<Integer>();
for (int n : numbers) {
if (n >= MIN && n <= MAX) subarray.add(n);
}
这是O(n),因为你只看一次每个数字。