- 存在重复元素 III
给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。
如果存在则返回 true,不存在返回 false。
示例 1:
输入:nums = [1,2,3,1], k = 3, t = 0
输出:true
示例 2:
输入:nums = [1,0,1,1], k = 1, t = 2
输出:true
示例 3:
输入:nums = [1,5,9,1,5,9], k = 2, t = 3
输出:false
提示:
0 <= nums.length <= 2 * 104
-231 <= nums[i] <= 231 - 1
0 <= k <= 104
0 <= t <= 231 - 1
注:要用long,因为如果是一个正的int最大减负的int最大就要越界。
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
Map<Long,Long> map = new HashMap<>();//用来保存当前数及其对应桶的序号
int n = nums.length;
for(int i = 0;i<n;i++){
//获得该数的桶序号
long id = getId(nums[i],t);
//i是下标,对于下标i,有效的下标为[i-k,i+k]。但是是遍历的,所以不用考虑[i,i+k]这部分
// ,如果i-(k+1)就证明前面已经有数已经不满足下标的条件了。要将其的桶删除
//例如k=3,数组为0,1,2,3,4.当前下标为4,值为4,所以下标为0值为0.有效的下标为:1,2,3,4.d
//当前下标为0的已经不满足了,因为4-(k+1)>=0 了。
if( i -(k+1) >=0){
//删除下标为 i-(k+1)的桶序
map.remove((long)getId(nums[i-(k+1)],t),(long)nums[i-(k+1)]);
}
//如果当前已经包含了该桶序
if(map.containsKey(id)){
return true;
}
//看前面的邻桶有没有
if(map.containsKey(id-1) && Math.abs(nums[i] - map.get(id - 1)) <= t){
return true;
}
//看后面的邻桶有没有
if(map.containsKey(id+1) && Math.abs(nums[i] - map.get(id + 1)) <= t){
return true;
}
map.put((long)getId(nums[i],t),(long) nums[i]);
}
return false;
}
public static int getId(int x,int t){
//如果x元素大于等于零,直接分桶
if(x>=0){
return x / ( t + 1 );
}else{
//如果x元素小于零,偏移后再分桶
return ( x + 1 )/( t + 1 ) - 1 ;
}
}
}