我不久前遇到了一个算法问题。
我需要查找存储在数组中的值是否在它的位置"放置"。 一个例子将更容易理解。
让我们取一个数组A = {-10,-3,3,5,7}。该算法将返回3,因为数字3在A [2](第3位)。 相反,如果我们采用数组B = {5,7,9,10},算法将返回0或false或其他任何内容。
数组始终排序!
我无法找到具有良好复杂性的解决方案。 (单独观察每个值并不好!)也许有可能通过使用类似于合并排序的方法,通过减少一半并验证这两半来解决该问题?
有人可以帮我这个吗? Java算法将是最好的,但伪代码也会对我有所帮助!
答案 0 :(得分:2)
这是一种算法(基于二进制搜索),用于查找具有最佳案例复杂度O(log(n))和最坏情况复杂度为O(n)的所有匹配索引:
1-检查位置m = array.length / 2
的元素2-如果值数组[m]严格小于m,则可以忘记数组的左半部分(从索引0到索引m-1),并递归地应用到右半部分。
3-如果array [m] == m,向计数器添加一个并递归地应用于两半
4-如果array [m]> m,忘记数组的右半部分并递归地应用到左半部分。
使用线程可以加速这里的事情。我想数组中没有重复。
答案 1 :(得分:1)
由于不存在重复项,您可以使用函数f(x): A[x] - x
单调的事实并应用二进制搜索来解决O(log n)
最坏情况复杂性中的问题。
您希望找到函数A[x] - x
取值为零的点。这段代码应该有效:
boolean binarySearch(int[] data, int size)
{
int low = 0;
int high = size - 1;
while(high >= low) {
int middle = (low + high) / 2;
if(data[middle] - 1 == middle) {
return true;
}
if(data[middle] - 1 < middle) {
low = middle + 1;
}
if(data[middle] - 1 > middle) {
high = middle - 1;
}
}
return false;
}
注意Java中的数组是0索引的 - 这就是我从数组中减去-1
的原因。
答案 2 :(得分:0)
如果你想找到数组中第一个数字,你只需要迭代数组:
static int find_in_place(int[] a) {
for (int i=0; i<a.length; i++) {
if (a[i] == i+1) {
return a[i];
}
}
return 0;
}
复杂度为O(n),平均成本为n / 2
答案 3 :(得分:0)
如果没有这样的元素,可以通过添加特殊条件来跳过迭代
if(a[0]>1 && a[a.length-1]>a.length){
//then don't iterate through the array and return false
return false;
} else {
//make a loop here
}
答案 4 :(得分:0)
只需使用二进制搜索0并用于比较数组中的值减去数组的索引。 O(log n)
答案 5 :(得分:0)
使用二分搜索(或类似的算法),你可以比O(n)更好。由于数组已排序,我们可以做出以下假设:
x
的值小于x-1
(a[x] <= x
),则您知道所有先前的值也必须小于其索引(因为不允许重复)< / LI>
a[x] > x + 1
所有后续值必须大于其索引(同样不允许重复)。使用它可以使用二进制方法并选择中心值,检查其索引并丢弃左/右部分(如果它符合上述条件之一)。当然,你会在a[x] = x + 1
时停止。