1. 题目描述
描述:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
2. 题目解析
2.1 考察问题
此问题考察数组查找问题。
查找重复元素,所以一定涉及到计数操作。
问题中提到所有数字在0到n-1之间,这个规律告诉可以直接用一个长度为n的1维数组计数,下标为目标数组中的对应元素,存储值为元素出现次数。
如果没有这个规律,那么只能考虑使用hashMap来计数了。
2.2 解决办法
- 遍历+1维数组计数
此方法想法简单,遍历目标数组,将对应计数加1,判断重复可以提前退出,我想你应该已经想到怎么做了。
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)
到这里,你是不是应该考虑优化一下,空间复杂度有点高,继续看。 - 遍历+目标数组原地计数
元素范围0到n-1,不仅仅允许直接使用数组而不是hashMap计数,而且考虑到元素有上限,可以以目标数组下标作为目标数组对应元素计数,此时计数不再加1,而是加n或者大于n的数即可。这样当考察到对应下标时,如果元素值已经大于n了,说明该下标出现过。
这里有一个问题,改变了目标数组元素值,那怎么保证每次能够拿到真正的元素呢,这时候就可以通过元素对n取余的操作来还原元素本来的值。
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)
3. 代码实现
3.1 1维数组计数
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
list_count = [0 for x in range(0, len(numbers))] ## 列表推导式,很实用
for num in numbers:
if list_count[num] == 1:
duplication[0] = num
return True
list_count[num] += 1
return False
3.2 目标数组原地计数
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
len_num = len(numbers)
for i in range(0, len_num):
index = numbers[i] % len_num ## 这步特别关键
numbers[index] += len_num
if numbers[index] >= 2*len_num:
duplication[0] = index
print(index)
return True
return False
4. 心得
我当时没有想到用元素取余方法还原本来的值,所以导致自己写出了很复杂的代码,虽然也正确,但是显然违反了代码的可读性和易实现性。
元素取余,元素位操作,元素的位的运算(异或,与,或)等都是些有用的技巧,可以帮助优化代码。
下面是没有用取余实现的代码,复杂度连我自己都有点看不懂了。
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
len_num = len(numbers)
for i in range(0, len_num):
if numbers[i] >= 2 * len_num:
duplication[0] = i
print("1 out = " + str(i))
return True
elif numbers[i] >= len_num:
if numbers[numbers[i] - len_num] >= len_num:
duplication[0] = numbers[i] - len_num
print("2 out = " + str(duplication[0]))
return True
numbers[numbers[i] - len_num] += len_num
else:
if numbers[numbers[i]] >= len_num:
duplication[0] = numbers[i]
print("3 out = " + str(duplication[0]))
return True
numbers[numbers[i]] += len_num
return False