題目:
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.
思路:
思路1: 笨辦法,雙重循環,逐個判斷,但是超時了。提交結果爲40 / 41 test cases passed
。
思路2: 建立一棵二叉搜索樹,保持節數數量小於或等於k。可以想象成一個k大小的滑動窗口,窗口內的元素存儲到二叉搜索樹中。每次找到比當前元素小的最大值以及比當前元素大的最小值,然後比較一下就可以了。
思路3: 公式(nums[i] - min) / (t+1)
可以求出nums[i]所在的bucket下標。爲什麼要除以t+1?因爲兩數字之差的取值範圍是0~t,共t+1個不同差值,除以t+1可以保證同一個bucket中的數字之差的範圍一定是0~t,一定符合要求。前一個bucket或後一個bucket中存放的數字也可能和當前bucket中存放的元素差值小於等於t,這是常識性問題了。此思路是效率最高的。
代碼實現:
思路1,超時代碼:
class Solution {
public:
long abs(long a, long b){
if (a > b){
return a-b;
}
return b-a;
}
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
for (int i = 0; i < nums.size(); ++i){
for (int j = i+1; j <= i + k && j < nums.size(); ++j){
if (abs(nums[i], nums[j]) <= t){
return true;
}
}
}
return false;
}
};
思路2:
class Solution {
public:
long abs(long a, long b){
if (a > b){
return a-b;
}
return b-a;
}
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if (nums.size() <= 0 || k <= 0 || t < 0){
return false;
}
set<long> my_set;
for (int i = 0; i < nums.size(); ++i){
if (i > k){
my_set.erase(nums[i-k-1]);
}
if (my_set.find(nums[i]) != my_set.end()){
return true;
}
auto iter1 = my_set.insert(nums[i]).first;
auto iter2 = my_set.insert(nums[i]).first;
if (iter1 != my_set.begin()){ // 小於nums[i]的最大值
iter1--;
if (abs(*(iter1), nums[i]) <= t){
return true;
}
}
iter2++;
if (iter2 != my_set.end()){ // 大於nums[i]的最小值
if (abs(*(iter2), nums[i]) <= t){
return true;
}
}
}
return false;
}
};
思路3:
class Solution {
public:
long abs(long a, long b){
if (a > b){
return a-b;
}
return b-a;
}
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if (nums.size() <= 0 || k <= 0 || t < 0){
return false;
}
unordered_map<long, long> my_map;
long min = *min_element(nums.begin(), nums.end());
long diff = t;
++diff;
for (int i = 0; i < nums.size(); ++i){
long buck_i = ((long)nums[i] - min) / diff;
if (my_map.find(buck_i) != my_map.end()){
return true;
}
if (my_map.find(buck_i-1) != my_map.end() && abs(my_map[buck_i-1], nums[i]) <= t){
return true;
}
if (my_map.find(buck_i+1) != my_map.end() && abs(my_map[buck_i+1], nums[i]) <= t){
return true;
}
my_map[buck_i] = nums[i];
if (i >= k){
my_map.erase((nums[i-k] - min) / diff);
}
}
return false;
}
};
參考:
https://www.bilibili.com/video/BV1e7411i7tW?from=search&seid=7991454138907471041