边工作边刷题:70天一遍leetcode: day 68

Contains Duplicate I/II/III

要点:I/II都很简单,对于II注意题意是是否在sliding window内存在相等的元素,不是所有相等的都间距小于k。重点说III:对于间距小于k这个条件,还是用sliding window。当检查一个新元素的时候,踢出最老的元素。同时要判断sliding window里有没有在当前元素t范围内的元素。为了找出范围内某个值,需要有序存储的数据结构。同时还要支持元素的insert和delete,所以用treeset tradeoff达到O(lgn)的time complexity。

另一种思路是sliding window里和某个元素满足值范围的只能在3个t大小的bucket里(一个自身桶和2个相邻桶),所以只需存bucket id,这个bucket id可以O(1)时间内计算出来。

  • 连续桶 vs. 随机桶:某value所在的bucket id是根据value在数轴上连续范围决定的,所以商作为bucket id。如果要把数轴上连续值分开,则要取模来确定bucket id
  • id-1和id+1 bucket: 如果值落在桶m里并且有值,那么可以返回true而中止程序。所以当前桶中要么有唯一值,要么没有值(所以1d map就可以表示)。而m-1和m+1桶也可能和当前值差<=t,所以要多2个检查
  • 负轴上的bucket id公式为(val+1)/t-1:why?这么想,-1要对应负轴上的第一个桶,如果按正轴的公式,应该是第0个桶。因为负数不是从0开始,所以整体向左偏移了1,要val+1,得到桶id以后,因为第0个桶实际对应-1,所以要再减1

错误点:

  • I很简单,但是不要和single number搞混了,那题是除了一个数之外全相同,所以可以用XOR解
  • t和k的理解:为什么要t++?bucket里可能value的个数为t+1即是值差在t范围内,e.g., t=0表示只有一个数,bucket size就是t+1,检查m-1和m+1时t已经++了,所以check是<t。同样对于k,因为是差值at most k,那么sliding window的size是k+1, 所以窗口外元素为i-k-1
  • 这题测试蛋疼的加了t<0,直接False,值差最少是0
class Solution(object):
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        s = set()
        for i in nums:
            if i in s:
                return True
            s.add(i)
        
        return False
class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        s = set()
        for i in xrange(len(nums)):
            if i>k: s.remove(nums[i-k-1])
            if nums[i] in s:
                return True
            s.add(nums[i])
        return False
class Solution(object):
    def containsNearbyAlmostDuplicate(self, nums, k, t):
        """
        :type nums: List[int]
        :type k: int
        :type t: int
        :rtype: bool
        """
        def getId(val, t):
            return val/t if val>=0 else (val+1)/t-1

        if t<0: return False
        hmap = {}
        t+=1
        for i in xrange(len(nums)):
            if i>k: del hmap[getId(nums[i-k-1], t)]
            id = getId(nums[i], t)
            print id
            if id in hmap: return True
            if id-1 in hmap and abs(nums[i]-hmap[id-1])<t: return True
            if id+1 in hmap and abs(nums[i]-hmap[id+1])<t: return True
            hmap[id]=nums[i]
        
        return False
posted @ 2016-06-04 05:35  absolute100  阅读(158)  评论(0编辑  收藏  举报