Leetcode 220. Contains Duplicate III 桶排序

231 篇文章 0 订阅

Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.

Example 1:

Input: nums = [1,2,3,1], k = 3, t = 0
Output: true

Example 2:

Input: nums = [1,0,1,1], k = 1, t = 2
Output: true

Example 3:

Input: nums = [1,5,9,1,5,9], k = 2, t = 3
Output: false

------------------------------------------------------------------------------

This is a good question!!! A sliding window with length t will results in TLE. Therefore, techniques for improvents are expected. Bucket partition is a good choice here. Cut nums into ... [0, t] [t+1,2t+1] ..., nums in the same bucket are obviously true. For every num, it's impossible to put 2 nums in the same adjacent bucket. So it has at most 1 num standing for the adjacent bucket. That's enough for this problem. 

class Solution:
    def containsNearbyAlmostDuplicate(self, nums, k, t):
        d = {}
        w = t+1
        for i in range(len(nums)):
            bid = nums[i] // w
            if (bid in d):
                return True
            elif (bid-1 in d and abs(d[bid-1]-nums[i]) <= t):
                return True
            elif (bid+1 in d and abs(d[bid+1]-nums[i]) <= t):
                return True
            d[bid] = nums[i] #bug3: 忘了
            if (i>=k): #bug1: 这次有效,下次就无效的桶
                d.pop(nums[i-k] // w) #bug2: i-k,瞎啊
        return False
s = Solution()
print(s.containsNearbyAlmostDuplicate([1,2,3,1],3,0))
print(s.containsNearbyAlmostDuplicate([1,0,1,1],1,2))
print(s.containsNearbyAlmostDuplicate([1,5,9,1,5,9], 2, 3))

Another solution is maintaining the sliding window as BST. BST requires 4 operations: getCeiling, getFloor, insert, remove(k). In c++, set (insert, erase, upper_bound, lower_bound) could be used. In java, TreeSet could be used. In Python, no corresponding object for the time being.

Copy from discussion:

 bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    set<int> window; // set is ordered automatically 
    for (int i = 0; i < nums.size(); i++) {
        if (i > k) window.erase(nums[i-k-1]); // keep the set contains nums i j at most k
        // |x - nums[i]| <= t  ==> -t <= x - nums[i] <= t;
        auto pos = window.lower_bound(nums[i] - t); // x-nums[i] >= -t ==> x >= nums[i]-t 
        // x - nums[i] <= t ==> |x - nums[i]| <= t    
        if (pos != window.end() && *pos - nums[i] <= t) return true;
        window.insert(nums[i]);
    }
    return false;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值