在线性时间内查找长度为 N、数字 1 到 N-1 的数组中的重复项,而无需使用额外的 obj/arr 来跟踪计数
Posted
技术标签:
【中文标题】在线性时间内查找长度为 N、数字 1 到 N-1 的数组中的重复项,而无需使用额外的 obj/arr 来跟踪计数【英文标题】:Find, in linear time, duplicate in array of length N, numbers 1 to N-1 without using additional obj/arr to keep track of a count 【发布时间】:2021-08-21 14:58:28 【问题描述】:我能够在线性时间和空间内完成这个 edabit 挑战,但挑战表明它只能使用相同的数组来完成(不需要额外的 obj/arr 来跟踪“已经看到”的数字。) 线性时间。
约束:长度为 'n' 的列表和范围从 1 到 n-1 的数字
// length N
// 1 to N - 1
const l = [5, 2, 1, 3, 4, 2]
function findDuplicate(list)
我认为这与在数组中的索引处跟踪“已经看到”的数字有关,但如果不需要再次循环遍历数组,我就无法做到这一点。
这就是我能够做到的:
function findDuplicate(list)
const dict =
for (let i=0; i < list.length; i++)
dict[list[i]] = dict[list[i]] + 1 || 1
if (dict[list[i]] === 2) return list[i]
但我使用obj
来跟踪“已经看到”的数字。
【问题讨论】:
嗯,您可以对数组进行排序,然后从索引 1 开始遍历它。如果数组中的当前数字与numbers[i - 1]
相同,那么这是您的副本。
对不起,忘了说它需要是线性时间。将其添加到问题中
你可以得到数组元素的总和,然后用n*(n+1)/2
(自然数的总和)减去它。 (或者,在这种情况下n*(n-1)/2
)。但是,这需要一个变量。这行得通吗?
您的数组中是否只有一个重复项?
只有一个副本
【参考方案1】:
由于您有一个只有一个重复的自然数数组,您可以得到直到n-1
的自然数之和,然后从数组元素的总和中减去它。
(5 + 2 + 1 + 3 + 4 + 2) - (1 + 2 + 3 + 4 + 5) = 2
这是一个sn-p:
function findDuplicate(list)
const n = list.length,
sum = list.reduce((a, b) => a + b, 0),
naturalSum = n * (n-1) / 2
return sum - naturalSum
console.log( findDuplicate([5, 2, 1, 3, 4, 2]) )
console.log( findDuplicate([1, 2, 3, 4, 3]) )
如果不允许,您也可以在不使用额外变量的情况下编写它:
function findDuplicate(l)
return l.reduce((a, b) => a + b, 0) - (l.length * (l.length - 1) / 2)
【讨论】:
【参考方案2】:const numbers = [5, 2, 1, 3, 4, 2];
const n = numbers.length - 1;
const expectedSum = (n * (n + 1)) / 2;
const sum = numbers.reduce((acc, val) => acc + val, 0);
const duplicate = sum - expectedSum ;
【讨论】:
【参考方案3】:也许[5, 2, 1, 3, 4, 2].reduce((acc, num, index) => (acc + num) - index, 0)
【讨论】:
以上是关于在线性时间内查找长度为 N、数字 1 到 N-1 的数组中的重复项,而无需使用额外的 obj/arr 来跟踪计数的主要内容,如果未能解决你的问题,请参考以下文章
在线性时间内对 0 到 n^2 – 1 范围内的 n 个数字进行排序
面试题3:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为