这个问题看起来很简单,很容易想到以下三种解法:
| 解法 | 时间 | 空间 |
|---|---|---|
| 两重循环 | n2n^2n2 | 1 |
| 先排序,再遍历 | nlognn\log nnlogn | 1 |
| 哈希表 | n | n |
但如果继续问,还有没有更高效的算法呢?
比如时间复杂度是 O(n)O(n)O(n), 空间复杂度为 O(1)O(1)O(1) 的算法?
😏😏😏
还真有!!
但是对 数组 有几个要求:
- 数组元素都是正数
- 数组是可写的
- 数组元素的最大值小于数组的长度
满足了以上三点。我们就可以使用下面这个算法了
def CheckDuplicates(A):
for i in range(0, len(A)):
if(A[abs(A[i])] < 0):
return abs(A[i])
else:
A[abs(A[i])] *= -1
return None
A = [3, 2, 1, 4, 2, 3]
print(CheckDuplicates(A)) # 2
咱们来看看具体的过程:
| 循环 | 数组状态 |
|---|---|
| 原始 | [3,2,1,4,2,3][3, 2, 1, 4, 2, 3][3,2,1,4,2,3] |
| i=0 | 把第A[0]A[0]A[0]个元素取负,A=[3,2,1,−4,2,3]A= [3, 2, 1, -4, 2, 3]A=[3,2,1,−4,2,3] |
| i=1 | 把第A[1]A[1]A[1]个元素取负,A=[3,2,−1,−4,2,3]A= [3, 2, -1, -4, 2, 3]A=[3,2,−1,−4,2,3] |
| i=2 | 把第A[2]A[2]A[2]个元素取负,A=[3,−2,−1,−4,2,3]A= [3, -2, -1, -4, 2, 3]A=[3,−2,−1,−4,2,3] |
| i=3 | 把第A[3]A[3]A[3]个元素取负,A=[3,−2,−1,−4,−2,3]A= [3, -2, -1, -4, -2, 3]A=[3,−2,−1,−4,−2,3] |
| i=4 | 发现第A[4]A[4]A[4]个元素已经是负数,说明之前有元素和 A[4]A[4]A[4] 相同,所以找到了重复元素 |
上述算法的本质是把原始数组用作计数器,节省了额外的空间,但是要求元素的取值范围在数组的长度范围之内,否则就没法对它计数了。
上述算法实现了时间复杂度是 O(n)O(n)O(n), 空间复杂度为 O(1)O(1)O(1) 的算法,还是非常巧妙滴 🤓

1万+

被折叠的 条评论
为什么被折叠?



