我的函数应该在给定的数组范围内返回缺少的元素。 因此,我首先对数组进行排序,并检查i和i + 1之间的差是否不等于1,我将返回缺少的元素。
// Given an array A such that:
// A[0] = 2
// A[1] = 3
// A[2] = 1
// A[3] = 5
// the function should return 4, as it is the missing element.
function solution(A) {
A.sort((a,b) => {
return b<a;
})
var len = A.length;
var missing;
for( var i = 0; i< len; i++){
if( A[i+1] - A[i] >1){
missing = A[i]+1;
}
}
return missing;
}
我确实喜欢上面的内容,但是如何更有效地编写它呢?
答案 0 :(得分:19)
您可以通过使用缺失值集来使用单循环方法。
在循环中,从缺失的集合中删除每个数字。
如果找到一个新的最小值,则所有缺失的数字都将添加到缺失数字集中,除了最小值和新的最大数字。
缺少的数字集最后包含结果。
function getMissing(array) {
var min = array[0],
max = array[0],
missing = new Set;
array.forEach(v => {
if (missing.delete(v)) return; // if value found for delete return
if (v < min) while (v < --min) missing.add(min); // add missing min values
if (v > max) while (v > ++max) missing.add(max); // add missing max values
});
return missing.values().next().value; // take the first missing value
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
答案 1 :(得分:5)
您可以将每个值放入sort
中,而不是Set
,找到最小值,然后从最小值开始进行迭代,检查集合中是否有相关数字{{1 }}。 (集合保证了O(N)
的查找时间)
O(1)
答案 2 :(得分:2)
好吧,从问题(因为它应该返回一个数字)和所有现有的解决方案(至少是示例)来看,列表看起来是唯一的。对于这种情况,我认为我们可以sum
整个数组,然后用这些数字之间的期望总和减去即可生成输出。
N个自然数之和
1 + 2 + ....... + i + ... + n
我们可以通过n * (n+1) / 2
现在假设在我们的数组中,最小值为i
,最大值为n
因此,我们可以评估i + (i+1) + ..... + n
A = 1 + 2 + ..... + (i-1) + i + (i+1) + .... n
(即n*(n+1)/2
)
B = 1 + 2 + ..... + (i-1)
和
C = A - B
将给我们( i +(i + 1)+ ... + n )
现在,我们可以迭代一次数组并评估实际的总和(假设D
),而C - D
将为我们提供缺失的数字。
让我们首先在每个步骤中都创建相同的内容(对于性能而言并非最佳,但更具可读性),然后我们将尝试在单个迭代中完成
let input1 = [2, 3, 1, 5],
input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10],
input3 = [3, 4, 5, 6, 8];
let sumNatural = n => n * (n + 1) / 2;
function findMissing(array) {
let min = Math.min(...array),
max = Math.max(...array),
sum = array.reduce((a,b) => a+b),
expectedSum = sumNatural(max) - sumNatural(min - 1);
return expectedSum - sum;
}
console.log('Missing in Input1: ', findMissing(input1));
console.log('Missing in Input2: ', findMissing(input2));
console.log('Missing in Input3: ', findMissing(input3));
现在,让我们尝试在单个迭代中完成所有操作(因为我们对max
,min
和sum
进行了3次迭代)
let input1 = [2, 3, 1, 5],
input2 = [2, 3, 1, 5, 4, 6, 7, 9, 10],
input3 = [3, 4, 5, 6, 8];
let sumNatural = n => n * (n + 1) / 2;
function findMissing(array) {
let min = array[0],
max = min,
sum = min,
expectedSum;
// assuming the array length will be minimum 2
// in order to have a missing number
for(let idx = 1;idx < array.length; idx++) {
let each = array[idx];
min = Math.min(each, min); // or each < min ? each : min;
max = Math.max(each, max); // or each > max ? each : max;
sum+=each;
}
expectedSum = sumNatural(max) - sumNatural(min - 1);
return expectedSum - sum;
}
console.log('Missing in Input1: ', findMissing(input1));
console.log('Missing in Input2: ', findMissing(input2));
console.log('Missing in Input3: ', findMissing(input3));
答案 3 :(得分:0)
如果数组为items
,而缺失diff
和当前const missingItem = items => [Math.min(...items)].map(min => items.filter(x =>
items.indexOf(x-diff) === -1 && x !== min)[0]-diff)[0]
之间的差为1:
O(n^2)
将给出([Math.min(...items)].map(min => items.filter(x =>
items.indexOf(x-diff) === -1 && x !== min))[0]).map(x => x-diff)
的复杂度。
它转换为:找到最小值,并检查数组中每个值n是否都没有n-diff值成员,这也不是最小值。对于所有尺寸差异不大的物品,都应为真。
要查找多个缺少的元素:
O((m^2)(n^2))
将提供m
,其中some
是缺少的成员数。
答案 4 :(得分:0)
发现了这个古老的问题,并想对此采取行动。我与https://stackoverflow.com/users/2398764/koushik-chatterjee有类似的想法,我想您可以通过知道总是只有一个缺少的元素来优化这一点。使用类似的方法但不使用最大值将导致以下结果:
function getMissing(arr) {
var sum = arr.reduce((a, b) => a + b, 0);
var lowest = Math.min(...arr);
var realSum = (arr.length) * (arr.length + 1) / 2 + lowest * arr.length;
return realSum - sum + lowest;
}
使用与上述相同的输入。我在几个浏览器的jsperf中运行了它,它的速度比其他答案要快。
https://jsperf.com/do-calculation-instead-of-adding-or-removing。
首先将所有内容相加,然后计算最小值,然后计算整数的和(如果恰好是最小值)。因此,举例来说,如果我们有2,3,4,5
,并且想要对它们求和,这与对0,1,2,3
进行求和,然后加上最低数+在这种情况下为2 * 4
,因为{{1} }将其恢复为原始。之后,我们可以计算出差异,但必须再次将其最小化。为了抵消这种变化,我们做了。
答案 5 :(得分:0)
您也可以使用while
循环,如下所示-
function getMissing(array) {
var tempMin = Math.min(...array);
var tempMax = tempMin + array.length;
var missingNumber = 0;
while(tempMin <= tempMax){
if(array.indexOf(tempMin) === -1) {
missingNumber = tempMin;
}
tempMin++;
}
return missingNumber;
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));
答案 6 :(得分:0)
我的方法是基于 O(N) 数组的就地排序,并且不使用任何其他数据结构。
function getMissing(ar) {
var mn = Math.min(...ar);
var size = ar.length;
for(let i=0;i<size;i++){
let cur = ar[i];
// this ensures each element is in its right place
while(cur != mn +i && (cur - mn < size) && cur != ar[cur- mn]) {
// swap
var tmp = cur;
ar[i] = ar[cur-mn];
ar[cur-mn] = tmp;
}
}
for(let i=0; i<size; i++) {
if(ar[i] != i+mn) return i+mn;
}
}
console.log(getMissing([2, 3, 1, 5]));
console.log(getMissing([2, 3, 1, 5, 4, 6, 7, 9, 10]));
console.log(getMissing([3, 4, 5, 6, 8]));