【lc刷题】217/219/220 存在重复元素/存在重复元素 II/存在重复元素 III _Day38(109-111/300)

109-111/300

存在重复元素

  1. 存在重复元素
    给定一个整数数组,判断是否存在重复元素。
     
    如果任何值在数组中出现至少两次,函数返回 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

  1. 存在重复元素 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

  1. 存在重复元素 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     
           
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值