leetcode笔记:Contains Duplicate III

一. 题目描述

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

二. 题目分析

题目大意是,给定一个整数数组,判断其中是否存在两个不同的下标ij,满足:| nums[i] - nums[j] | <= t 且下标:| i - j | <= k

可以想到,维护一个大小为k的二叉搜索树BST,遍历数组中的元素,在BST上搜索有没有符合条件的数对,若存在则直接返回true,否则将当前元素数对插入BST,并更新这个BST(若此时BST的大小已为k,需要删掉一个值)。保证BST的大小小于或等于为k,是为了保证里面的数下标差值一定符合条件:| i - j | <= k。实现时,可使用mulitset来实现BST

mulitset是一个有序的容器,里面的元素都是排序好的,且允许出现重复的元素,支持插入,删除,查找等操作,就像一个集合一样。multiset内部以平衡二叉树实现。因此所有的操作的都是严格在O(logn)时间之内完成,效率较高。

三. 示例代码

// 方法一,由于vector无序,需要排列一次
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
         if(nums.size() < 2) return false;
         vector<pair<long, int>> value;
         for (int i = 0; i < nums.size(); ++i)
            value.push_back(pair<long, int>(nums[i], i));
         sort(value.begin(), value.end());
         for (int i = nums.size() - 1; i >= 1; --i)
         {
             for (int j = i - 1; j >= 0; --j)
             {
                 if (value[i].first - value[j].first > t) break;
                 else if (abs(value[i].second - value[j].second) <= k) return true;
                 else continue;
             }
         }
         return false;
    }
};
// 方法二
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    multiset<int> window; // 维护一个大小为k的窗口
    for (int i = 0; i < nums.size(); ++i) {
        if (i > k) window.erase(nums[i - k - 1]); // 保持window内只有最新k个元素,间接保证窗口内各元素下标不超过k
        auto pos = window.lower_bound(nums[i] - t); 
        if (pos != window.end() && *pos - nums[i] <= t) return true;
        window.insert(nums[i]);
    }
    return false;
}

四. 小结

练习了集合类set和mulitset的使用。相关题目有:Contains Duplicate II和Contains Duplicate I

你可能感兴趣的:(LeetCode,C++,算法,二叉树,BST)