...
if (!arr[nums[i]]) {
arr[nums[i]] = 1;
continue;
}
result.push(nums[i]);
另外在leetcode评论区里也有比较好的解法,具体思想可以参考下
给对应下标数字取反,如果已经时负数,那证明之前出现过了,那么就将该元素添加到数组中去。
function findDuplicates(nums) {
let result = [];
for (let i = 0; i < nums.length; i++) {
let num = Math.abs(nums[i]);
if (nums[num - 1] > 0) {
nums[num - 1] *= -1;
} else {
result.push(num);
}
}
return result;
}
leetcode:442 数组中重复的数据
解题思路
复杂度 O(n),首先肯定只能循环一次数组,且数组中有重复的元素,并且找出重复的元素并返回。
具体实现代码示例:
首先以上代码块已经实现了寻找数组中的重复数字了。
但是我们要具体分析下时间复杂度为什么是 O(n)
解释一下什么是
时间复杂度O(n)
百度相关资料解释,O(n)实际上是一个线性的一次函数,可以看成 y = x;y 随着 x 的增长而增长,具体一张图加深下印象
另外还有一个比较费脑壳的词
空间复杂度O(1)
不管
x
怎么变化,y
始终是一个定值在时间复杂度 O(n)具体是怎么样
我们会发现 n=10,下面循环就循环的 10 次,如果 n=100,那么就会循环 100 次。,所以
y
是随着n
呈线性变化的。如果是双层循环呢,那么此时时间复杂度就是 O(n^2),比如
因为双层循环,那么时间复杂循环就是 100 次了,所以复杂度就 O(n^2)了
如果没有循环,在数组中寻找指定元素呢,那么复杂度就 O(1);
总结以上时间复杂度,有一层循环就是O(n),如果没有循环,在数组中找值O(1),如果是双层循环那么时间复杂度就是O(n^2);
很显然我们这道题使用的是一层循环,那么复杂度就是 O(n),我们借用了一个
arr = new Array(n).fill(0)
其实是在n
长度的数组中快速拷贝赋值一n
个长度的 0。但是我们发现在循环中,我们使用了
continue
,continue
在for
循环的作用是跳过本次循环,也正是利用这一点,我们将当下数组值作为arr
的索引,并设置一个值。关于
continue
跳过本次循环,我们可以写个简单的例子测试一下当
i===2
时,跳过当前循环,那么此时后面的result.push(i)
自然就不会有效了。另外一个对应就是
break
;很显然
break
是中止循环,当i=2
时,整个循环就结束了。再来分析,其实我们会发现,很有意思就是
默认情况数组中
arr
所有数据都是 0,我们用nums[i]
也就是目标元素的值作为arr
索引,并且标记为 1,当下次有重复的值时,其实此时,就取反操作了。所以就不会走continue
了,那么此时push
就是获取对应之前的重复值了。另外在
leetcode
评论区里也有比较好的解法,具体思想可以参考下给对应下标数字取反,如果已经时负数,那证明之前出现过了,那么就将该元素添加到数组中去。