剑指offer二刷——数组专题——数组中重复的数字
题目描述
我的想法
最开始想到的是用“字典”,依次记录每个数字出现的次数,这就要遍历数组并且创建字典,感觉空间上占用较大。
# -*- coding:utf-8 -*- class Solution: # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] # 函数返回True/False def duplicate(self, numbers, duplication): # write code here dic={} for i in numbers: if i in dic: duplication[0]=i return True else: dic[i]=1 return False
时间复杂度o(n),空间复杂度o(n)
然后想到用数组代替字典,因为数组内所有数字都在0到n-1的范围内,那么我可以创建一个大小为n的数组a,初始值都为0,利用数组下标记录a[i]是否为0。如果a[i]==0,那么说明该数字是第一次遍历到,令a[i]=1;如果a[i]==1,那么说明该数字是第二次遍历到,该数字重复,令duplication[0]=i,返回True;如果遍历完全后没有return False,那么就return True。
# -*- coding:utf-8 -*- class Solution: # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] # 函数返回True/False def duplicate(self, numbers, duplication): # write code here if len(numbers)==0: return False a=[0]*len(numbers) for i in numbers: if not a[i]: a[i]=1 else: duplication[0]=i return True return False
时间复杂度o(n),空间复杂度o(n)
然后我觉得以上两种方法,空间复杂度都为o(n),应该还有空间复杂度更小的解法。但我想不出来了。
官方解法
也是利用数组下标的性质,但是不是新建一个数组,而是利用指针。i 从0的位置开始,一定要找到每个 i 对应的数字,即numbers[i]=i,才能继续下一个,如果交换过程中发现已经是numbers[i]=i,那么当前要交换的数字就是重复的数字。
1 # -*- coding:utf-8 -*- 2 class Solution: 3 # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] 4 # 函数返回True/False 5 def duplicate(self, numbers, duplication): 6 # write code here 7 if not numbers or len(numbers)==0:return False 8 for i in range(len(numbers)): 9 while i!=numbers[i]: 10 if numbers[i]==numbers[numbers[i]]: 11 duplication[0]=numbers[i] 12 return True 13 # swap 14 # numbers[i],numbers[numbers[i]] = numbers[numbers[i]],numbers[i]不可行 15 tmp=numbers[i] 16 numbers[i]=numbers[numbers[i]] 17 numbers[tmp]=tmp 18 return False
时间复杂度o(n),空间复杂度o(1)
上述代码官方给的步骤:
-
设置一个指针i指向开头0,
-
对于arr[i]进行判断,如果arr[i] == i, 说明下标为i的数据正确的放在了该位置上,让i++
-
如果arr[i] != i, 说明没有正确放在位置上,那么我们就把arr[i]放在正确的位置上,也就是交换
arr[i] 和arr[arr[i]]。交换之后,如果arr[i] != i, 继续交换。 -
如果交换的过程中,arr[i] == arr[arr[i]],说明遇到了重复值,返回即可。
如下图:
使用内置函数的解法
使用set函数可以删除无序数组中重复的数字。 https://www.runoob.com/python/python-func-set.html
使用 collections.Counter.most_common(1) 可以找到数组中重复最多的数字。https://blog.csdn.net/qwe1257/article/details/83272340
1 # -*- coding:utf-8 -*-\ 2 from collections import Counter 3 class Solution: 4 # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] 5 # 函数返回True/False 6 def duplicate(self, numbers, duplication): 7 # write code here 8 if len(numbers)==0 or not numbers:return False 9 if len(numbers)==len(set(numbers)):return False 10 duplication[0]=Counter(numbers).most_common(1)[0][0] 11 return True