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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值