(python)剑指Offer:数组中重复的数字
问题描述
在长度为n的数组中,所有的元素都是0到n-1的范围内。 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字。 例如,输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出为2或3。
解题思路
1、判断输入数组有无元素非法
2、从头扫到尾,只要当前元素值与下标不同,就做一次判断,numbers[i]与numbers[numbers[i]],相等就认为找到了重复元素,返回true,否则就交换两者,继续循环。直到最后还没找到认为没找到重复元素,返回false
时间复杂度:O(n),空间复杂度:O(1)
解题代码(python实现)
1 2 3 4 5 6 7 8 9 10 11 | #在长度为n的数组中,所有的元素都是0到n-1的范围内。 数组中的某些数字是重复的,但不知道有几个重复的数字, #也不知道重复了几次,请找出任意重复的数字。 例如,输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出为2或3 def repeat_num(li): for index, value in enumerate (li): if index ! = value: li[index], li[value] = li[value], li[index] if index ! = value and value = = li[value]: return li[index] li = [ 0 , 1 , 2 , 3 , 3 , 4 , 6 , 4 ] print (repeat_num(li)) |
扩展:
题目描述:
在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但是不能修改输入的数组。
思路:
采用二分法查找,时间复杂度为 O(nlogn)
在数字 1
~n
中取中间值 m
= (1+n) / 2, 此时数字包括 1
~m
, m+1
~n
两段;
遍历数组,获得数字 1
~m
的个数;
如果数字 1
~m
的个数大于 m
,说明 1
~m
这一段内肯定有重复数字,那么在这一段内继续取中间值比较;
如果数字 1
~m
的个数等于 m
,这一段不一定有重复数字,比较后一段;
如果数字 1
~m
的个数小于 m
,说明 m+1
~n
这一段一定有重复数字,在后一段取中间值比较;
按照上述方法一直取中间值比较,直到只剩一个数字且这个数字出现次数超过 1 ,该数字即为重复数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | class solution(): def duplicate( self ,numbers): if numbers = = []: return False length = len (numbers) start = 1 end = length - 1 while end > = start: middle = (end - start) / / 2 + start count = self .countNum(numbers, length, start, middle) if end = = start: if count > 1 : return True else : break if count > middle - start + 1 : end = middle else : start = middle + 1 return False def countNum( self , numbers, length, start, end): count = 0 for i in range (length): if numbers[i] < 1 or numbers[i] > length: return False if start < = numbers[i] < = end: count + = 1 return count ss = solution() print (ss.duplicate([ 4 , 2 , 3 , 1 , 2 , 5 ])) print (ss.duplicate([ 4 , 2 , 3 , 1 ])) |
这种方法虽然不需要辅助空间O(n),但是后面每半个区间都需要遍历整个数组,函数countNum将被调用O(logn)次,每次需要O(n)的时间,因此总的时间复杂度是O(nlogn),空间复杂度为O(l)。相当于用时间换空间了。
现在来总结下关于数组中重复数字的问题,利用辅助空间的话,时间和空间复杂度都是O(n);利用下标于数字对应关系的话时间复杂度是O(n),空间复杂度是O(l),但是需要改变数组;利用二分查找类似思路的方法,时间复杂度是O(nlogn),空间复杂度O(l),所以要问清楚面试官他想要空间效率高的呢?还是时间效率高的呢?能不能改变数组呢?一方面体现交流能力,一方面能最快的写出答案。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步