JZ3:一维数组中找出任一重复的元素
```python
'''
JZ3:输入一个长为n的数组,元素取值为0-n-1,找出数组中的人一个重复元素
解题思路:
1、边界条件:空数组/无重复情况返回-1
2、解法:
A1 排序后遍历比较相邻两个元素是否相等
A2 用空间换时间,用列表、集合、字典等容器储存唯一值
A3 重排序索引对齐,将索引和值大小对应,不能对应的即重复元素:依次遍历,不对应的元素放到相应位置,交换值
A4 二分查找,不断缩小取值区间,直到left=right,并且区间长度<元素个数
3、测试
T1 空数组
T2 长度为1的数组
T3 长度为2的数组
'''
from typing import List
class Solution:
def duplicate(self, numbers: List [int])->int:
'''排序后遍历
时间复杂度:排序 nlogn + n次循环
空间复杂度:O(1)'''
numbers.sort()
if len(numbers) == 1:
return -1
for i in range(len(numbers)):
if numbers[i] == numbers[i+1]:
return numbers[i]
return -1
def duplicate1(self, numbers: List[int])->int:
'''使用容器存储唯一值
LIST/SET/DCIT
时间复杂度O(n) 空间复杂度O(n)
以空间换时间'''
value_set = set()
for num in numbers:
if num in value_set:
return num
else:
value_set.add(num)
return -1
def duplicate2(self, numbers: List[int])->int:
'''
索引对齐数组值,将空间复杂度降为O(1)
1、从头遍历数组,如果索引对齐进入下次迭代
2、如果索引未对齐,将交换元素,继续比较索引是否对齐:每个元素最多交换两次即可对齐
3、停止条件:交换的两元素相等、未找到重复元素返回-1
'''
for i in range(len(numbers)):
while numbers[i] != i:
if numbers[i] == numbers[numbers[i]]:
return numbers[i]
else:
temp = numbers[i]
numbers[i] = numbers[temp]
# 继续比较新的numbers[i]是否对齐
numbers[temp] = temp
return -1
def count_range(self, numbers: List[int], left, right)->int:
if len(numbers) == 0:
return 0
count = 0
for i in range(len(numbers)):
if numbers[i]>=left and numbers[i]<=right:
count += 1
return count
def duplicate3(self, numbers: List[int])->int:
'''
1、 取值范围0~n-1:分割此区间
2、 当元素数量大于区间长度,必然存在重复的元素
3、 继续分割区间直到区间长度为1,但是count>1时,返回left/right
'''
if len(numbers) == 0:
return -1
left, right = 0, len(numbers)-1
while left <= right:
mid = (left + right) // 2
count = self.count_range(numbers, left, mid)
if left == right:
if count > 1:
return left
else:
break
if count > mid - left + 1:
right = mid
else:
left = mid + 1
return -1
if __name__ == "__main__":
solution = Solution()
# 排序后遍历
nums = [2, 3, 1, 0, 2, 5, 3]
print(solution.duplicate(nums))
nums1 = []
print(solution.duplicate(nums1))
nums2 = [0]
print(solution.duplicate(nums2))
nums3 = [1, 1]
print(solution.duplicate(nums3))
# 使用额外空间存储唯一值:空间换时间
print("_______"*8)
print(solution.duplicate1(nums))
print(solution.duplicate1(nums1))
print(solution.duplicate1(nums2))
print(solution.duplicate1(nums3))
# 索引对齐
print("_______" * 8)
print(solution.duplicate2(nums))
print(solution.duplicate2(nums1))
print(solution.duplicate2(nums2))
print(solution.duplicate2(nums3))
# 二分查找
print("_______" * 8)
print(solution.duplicate3(nums))
print(solution.duplicate3(nums1))
print(solution.duplicate3(nums2))
print(solution.duplicate3(nums3))