109-111/300
存在重复元素
- 存在重复元素
给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true
'''
sort
'''
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
nums.sort()
for i in range(1, len(nums)):
if nums[i] == nums[i-1]:
return True
return False
'''
pythonic
'''
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
return len(set(nums)) < len(nums)
'''
hashTable:
'''
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
mydict = collections.Counter()
for num in nums:
mydict[num] += 1
if mydict[num] > 1:
return True
return False
#modified
def containsDuplicate(self, nums: List[int]) -> bool:
mydict = {}
for num in nums:
if num in mydict:
return True
mydict[num] = 1
return False
存在重复元素 II
- 存在重复元素 II
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。
示例 1:
输入: nums = [1,2,3,1], k = 3
输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1
输出: true
示例 3:
输入: nums = [1,2,3,1,2,3], k = 2
输出: false
class Solution:
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
mydict = {}
for i, n in enumerate(nums):
if n in mydict and i - mydict[n] <= k:
return True
mydict[n] = i
return False
存在重复元素 III
- 存在重复元素 III
给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。
示例 1:
输入: nums = [1,2,3,1], k = 3, t = 0
输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1, t = 2
输出: true
示例 3:
输入: nums = [1,5,9,1,5,9], k = 2, t = 3
输出: false
思路1: intuitive
暴力:k是idex的差,那么固定滑动窗口,在里面找符合条件的val的差值
暴力优化:排序(带上index)先看是否符合差值(符合条件的最小差值为0,排序后的优势就在这里),然后再看index是否符合条件。
先决条件:
“两个不同的索引 i 和 j”,证明至少俩数,而且i-j !=0;
k, t 为绝对值,不能为负(也不知道为啥测试集里会放负数?)
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
n = len(nums)
if k <= 0 or t < 0 or n <= 1: return False
lst = sorted([(v,i) for i,v in enumerate(nums)])
for i in range(n-1):
j = i+1
while j < n and lst[j][0] - lst[i][0] <= t:
if abs(lst[j][1] - lst[i][1]) <= k:
return True
j += 1
return False
思路2: bucket sort
怎么找到与当前数差值为t且index不超过k的数?
· 如何找到index不超过k的数?
k是index的差值,举个形象的例子,我们给每个数贴上bucket号,但我们只有k张贴纸,当前数正好用完,我们就要把头里的贴纸撕下来,给后面的人备好。
· 那么,贴纸上该写啥?
譬如上帝视角,我们有10个数[3, 5, 9, 22, 9, 0, 13, 1, 14, 19],最大的是22,最小的是0,t = 3,我们来看大家的bucket号是怎么弄的:
0号bucket里放3个数:0、1、2,
1号bucket里放3个数:3、4、5,
2号bucket里放3个数:6、7、8,
…
6号bucket里放3个数:18、19、20
7号bucket里放3个数:21、22、23
…
某号bucket里放t个数
bucket号 = floor(当前数值除以t)
[(0, 0), (0, 1), (1, 3), (1, 5), (3, 9), (3, 9), (4, 13), (4, 14), (6, 19), (7, 22)]
· 如何找到与当前数差值为t的数?
当前数bucket号已经得出,我们只需要看(虚拟空间里的)的前面一个bucket/自己bucket/后面一个bucket里的数 与当前数的差值是否为t,譬如上面的例子,跟22最多差3的数,肯定在19~25里,也就是6号/7号/8号buckets。
class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
if k <= 0 or t < 0 or len(nums) <= 1: return False
buckets = {}
for i, num in enumerate(nums):
_id = num//t if t else num #挥舞着贴纸
for _i in (_id-1, _id, _id+1):
#贴前先瞅几眼,因为一个bucket里的(最大-最小)控制在t内
#但凡bucket里多了一个,肯定返回true
if _i in buckets and abs(buckets[_i] - num) <= t:
return True
buckets[_id] = num #pia叽贴上
if i - k >= 0: #为了给下一个人准备贴纸,撕头里那个!
del buckets[nums[i-k]//t if t else nums[i-k]]
return False