• [Leetcode]220. Contains Duplicate III


    这是Leetcode第220题,给定一个整数数组,问是否存在两个数差距最多为(t),两数的间隔最大为(k)
    很明显,这里需要用到一个大小为(K)的窗口,每次判断窗口内是否存在每个数差值满足(<=t)的条件。每一次都进行朴素的判断,需要用(O(K))的时间复杂度,主体循环一次就是(O(NK))。则,我们优化的目标是,怎么在(O(1))时间判断窗口内是否存在满足条件的数。
    这里使用了hash Map的思路,更准确地讲,是桶排序的思想。将每个数(n)映射到(n//t)的key上,如果(t)等于零,则是(n)本身,每次判断(key-1)(key+1)上面的数即可。具体代码如下:

    class Solution:
        def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
            n=len(nums)
            if t==0 and n==len(set(nums)):
                return False
            dic = {}
            for i, v in enumerate(nums):
                # t == 0 is a special case where we only have to check the bucket
                # that v is in.
                key, offset = (v // t, 1) if t else (v, 0)
                for idx in range(key - offset, key + offset + 1):
                    if idx in dic and abs(dic[idx] - nums[i]) <= t:
                        return True
    
                dic[key] = v
                if i >= k:
                    # Remove the bucket which is too far away. Beware of zero t.
                    del dic[nums[i - k] // t if t else nums[i - k]]
    
            return False
    

    使用空间来降低时间复杂度是一个很常见的套路了。但更多时候,我们需要思考如下使用空间记录更多的信息,来帮助我们排除干扰,降低时间复杂度。

    扩展

    [Leetcode]164. Maximum Gap 最大间距

    求一个无序数组排序后相邻数的差距的最小值,如果使用基于比较的排序绝对是(O(nlogn)) 的。使用桶在这道题是有天然优势的,最大gap肯定是出现在后一个有效桶的min与前一个有效桶的max之间,不用去比较桶内元素的大小。
    具体代码如下:

    class Solution:
        def maximumGap(self, nums: List[int]) -> int:
            if len(nums) <= 1 :
                return 0
    
            minValue = 2**31-1
            maxValue = -2**31
            for num in nums:
                minValue = min(minValue, num)
                maxValue = max(maxValue, num)
    
            bucket_range = (maxValue - minValue) // len(nums) + 1
            bucket_num = ((maxValue - minValue) // bucket_range) + 1
    
            hashmapMax = {}
            hashmapMin = {}
            for i in range(len(nums)):
                bucket_id = (nums[i]-minValue) // bucket_range
                if not bucket_id in hashmapMax:
                    hashmapMax[bucket_id] = nums[i]
                    hashmapMin[bucket_id] = nums[i]
                else:
    
                    hashmapMax[bucket_id] = max(hashmapMax[bucket_id],nums[i])
                    hashmapMin[bucket_id] = min(hashmapMin[bucket_id],nums[i])
    
            prev = 0
            res = 0
    
            for i in range(1,bucket_num):
                if not i in hashmapMax:
                    continue
                if not prev in hashmapMax:
                    continue
                res = max(res, hashmapMin[i] - hashmapMax[prev])
                prev = i
            return res
    

    [Leetcode]128. Longest Consecutive Sequence 最长连续序列

    给定一个未排序的整数数组,找出最长连续序列的长度。要求算法的时间复杂度为 (O(n))。利用Map存储元素nums[i]的值以及其所在连续序列的长度,此时基本只有两种情况:

    • 数组中出现过元素nums[i]-1或nums[i]+1,意味着当前元素可以归入左或右序列,那么此时假如左右序列的长度分别为left、right,那么显然加入nums[i]后,这整段序列的长度为 1+left+right,而由于这一整段序列中,只可能在左右两端扩展,所以只需要更新左右两端的value值即可。
    • 数组中未出现过元素nums[i]-1或nums[i]+1,意味着当前元素所在的连续序列就是自身(只有自己一个元素)。
      另外,注意去重即可
    class Solution:
        def longestConsecutive(self, nums: List[int]) -> int:
            nums_set = set(nums)
            dic = {}
            res = 0
            for num in nums_set:
                left = dic.get(num-1,0)
                right = dic.get(num+1,0)
                cur = left+right+1
    
                dic[num-left] = cur
                dic[num+right] = cur
                res = max(res,cur)
            return res
    
  • 相关阅读:
    BZOJ3105: [cqoi2013]新Nim游戏 博弈论+线性基
    BZOJ3759: Hungergame 博弈论+线性基
    NOI模拟赛Day2
    期望dp BZOJ3450+BZOJ4318
    NOI模拟赛 Day1
    NOI模拟 热身赛T1
    【BZOJ4260】 Codechef REBXOR 可持久化Trie
    【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树
    【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队
    【bzoj3527】[Zjoi2014]力 FFT
  • 原文地址:https://www.cnblogs.com/hellojamest/p/11617441.html
Copyright © 2020-2023  润新知