我遇到一个问题,我必须在数组中找到缺少的数字并将它们添加到一个集合中。
问题是这样的:
大小(n-m)的数组,数字来自1..n,其中m个缺失。
在O(日志)中找到所有缺失的数字。数组已排序。 示例:
n = 8
arr = [1,2,4,5,6,8]
m = 2
结果必须是{3,7}。
到目前为止,这是我的解决方案,想知道如何计算解决方案的大部分内容。我见过的大多数解决方案都使用了分而治之的方法。我如何计算下面的算法的大哦?
ps如果我不符合要求,有什么方法可以做到这一点,而不必递归吗?我真的不是递归的粉丝,我简直无法理解它! :(
var arr = [1,2,4,5,6,8];
var mySet = [];
findMissingNumbers(arr);
function findMissingNumbers(arr){
var temp = 0;
for (number in arr){ //O(n)
temp = parseInt(number)+1;
if(arr[temp] - arr[number] > 1){
addToSet(arr[number], arr[temp]);
}
}
}
function addToSet(min, max){
while (min != max-1){
mySet.push(++min);
}
}
答案 0 :(得分:2)
你想要看两件事,你已经指出了一件事:你为循环“for(number in arr)”迭代了多少次?如果数组包含n-m个元素,那么这个循环应该迭代n-m次。然后查看您在循环中执行的每个操作,并尝试找出每个操作的最坏情况(或典型)方案。 temp = ...行应该是一个恒定的成本(比如每个循环1个单元),条件是常量成本(比如每个循环1个单元),然后是addToSet。 addToset更难以分析,因为它不是每次都调用,而且每次调用它的成本可能会有所不同。所以也许你想要的是,对于m个缺失元素中的每一个,addToSet将执行1次操作...总共m次操作(你不知道它们何时会发生,但是所有m必须发生在某一点)。然后将所有费用加起来。
nm循环迭代,在每一个中你做2个操作总共2个(nm)然后加上addToSet完成的m个操作,总共有2n-m~2n(假设m比n小)。这可能是O(n-m)或O(n)(如果它是O(n-m),它也是O(n),因为n> = n-m。)希望这有帮助。
答案 1 :(得分:1)
在你的代码中,你有一个复杂的O(n),因为你检查了数组的n索引。更快的方法就是这样:
请注意,您可以进行一些优化,例如,您可以直接检查数组是否具有正确的大小并返回空数组。这取决于你的问题。
我的算法也在O(n)中,因为你总是采用最差的数据集。就我而言,我会错过阵列末尾的一个数据。所以从技术上来说它应该是O(n-1)但是在n前面的常数可以忽略不计(假设非常高)。这就是为什么你必须记住平均复杂性。
答案 2 :(得分:0)
这里的价值是一个更简洁的算法实现(javascript):
var N = 10;
var arr = [2,9];
var mySet = [];
var index = 0;
for(var i=1;i<=N;i++){
if(i!=arr[index]){
mySet.push(i);
}else{
index++;
}
}
这里的大(O)是微不足道的,因为只有一个循环,它每次迭代都会以恒定的成本运算精确运行N次。
答案 3 :(得分:-2)