目录
- 1、题目描述:
- 2、方法一:排序
- 思路:
- 代码:
- 3、方法二:哈希表
- 思路:
- 代码:
- 4、方法三:原地交换
- 思路:
- 代码:
首先将数组从小到大排序;然后再遍历一遍数组,检查相邻元素是否相等,若相等则找到了一个重复的元素,直接返回这个元素即可。
class Solution: def findRepeatNumber(self, nums: List[int]) -> int: nums.sort() # 从小到大排序 for i in range(1, len(nums)): if nums[i-1] == nums[i]: # 相等则直接返回 return nums[i]
由于要排序,因此时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn);空间复杂度为 O ( 1 ) O(1) O(1)。
方法一主要时间用在了排序上,那么我们不用排序能否做出来呢?这里可以使用哈希表来做记录。具体来说:遍历数组,将元素作为哈希表的key,出现次数作为value,一旦出现次数大于1则直接返回当前元素即可。
class Solution: def findRepeatNumber(self, nums: List[int]) -> int: hash_table = {} # key为元素,value为出现次数 for i in range(len(nums)): try: hash_table[nums[i]] += 1 return nums[i] # 上面语句没报错,说明重复了 except: hash_table[nums[i]] = 1
时间复杂度为 O ( n ) O(n) O(n);空间复杂度为 O ( n ) O(n) O(n)。
以上两种方法都很朴素,但是一个时间复杂度高,一个空间复杂度高,不足以拿到offer,那么要是面试官要求:时间复杂度为 O ( n ) O(n) O(n);空间复杂度为 O ( 1 ) O(1) O(1)呢?这个题又怎么解决?
直接看官方的解答:
小技巧:如果觉得不好想,用例子模拟,如下面代码这样。
class Solution: def findRepeatNumber(self, nums: List[int]) -> int: i = 0 for i in range(len(nums)): # 以[0,1,2,3,2,5,3]为例,假设此时i指向第二个2,然后就好理解了 while i != nums[i]: if nums[nums[i]] == nums[i]: # 两个元素相等了 return nums[i] nums[nums[i]], nums[i] = nums[i], nums[nums[i]] # 调整使得:元素和下标对应
注意:代码中尽管有一个两重循环,但每个数组最多只要交换两次就能找到属于它自己的位置,因此总的时间复杂度时 O ( n ) O(n) O(n)。
当然,空间复杂度显然是 O ( 1 ) O(1) O(1)。