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.
思路
基本思路是,假设当前运行到nums[i]的位置,则需要往前看k个数,并且找到其中任意一个数x满足 nums[i]-t <= x <=nums[i]+t。可以利用一个大小为k的二叉搜索树解决搜索范围的问题(问题就转变为:找到第一个>=nums[i]-t的数,判断他是否<=nums[i]+t)。整个算法的时间复杂度是O(N * logk),N为数组长度。
下面代码中用set实现,set是用红黑树实现的。
代码
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if(nums.empty() || k<1 || t<0)
return false;
k++;
set<int> kNumSet;
for (int i=0; i<nums.size(); i++){
if(i >= k){
int oldVal = nums[i-k];
kNumSet.erase(oldVal);
}
auto l_bound = kNumSet.lower_bound(nums[i] - t);
if(l_bound != kNumSet.end()){
if(*l_bound - t <= nums[i])
return true;
}
kNumSet.insert(nums[i]);
}
return false;
}
};
int querySegTree(int treeIndex, int lo, int hi, int i, int j)
{
// 查询 arr[i..j]
if (lo > j || hi < i) // 片段完全超出范围
return 0; // 表示一个null节点
if (i <= lo && j >= hi) // 片段完全在范围内
return tree[treeIndex];
int mid = lo + (hi - lo) / 2; // 当前片段与查询范围有部分重合。递归到深一层。
if (i > mid)
return querySegTree(2 * treeIndex + 2, mid + 1, hi, i, j);
else if (j <= mid)
return querySegTree(2 * treeIndex + 1, lo, mid, i, j);
int leftQuery = querySegTree(2 * treeIndex + 1, lo, mid, i, mid);
int rightQuery = querySegTree(2 * treeIndex + 2, mid + 1, hi, mid + 1, j);
// 合并查询结果
return merge(leftQuery, rightQuery);
}
// call this method as querySegTree(0, 0, n-1, i, j);
// Here [i,j] is the range/interval you are querying.
// This method relies on "null" nodes being equivalent to storing zero.
void updateValSegTree(int treeIndex, int lo, int hi, int arrIndex, int val)
{
if (lo == hi) { // 叶子节点,更新元素值.
tree[treeIndex] = val;
return;
}
int mid = lo + (hi - lo) / 2; // 向更深层递归以查找对应节点
if (arrIndex > mid)
updateValSegTree(2 * treeIndex + 2, mid + 1, hi, arrIndex, val);
else if (arrIndex <= mid)
updateValSegTree(2 * treeIndex + 1, lo, mid, arrIndex, val);
// 合并更新结果
tree[treeIndex] = merge(tree[2 * treeIndex + 1], tree[2 * treeIndex + 2]);
}
// call this method as updateValSegTree(0, 0, n-1, i, val);
// Here you want to update the value at index i with value val.