剑指 Offer II 057. 值和下标之差都在给定的范围内

121 阅读1分钟

剑指 Offer II 057. 值和下标之差都在给定的范围内

最简单的方法,两次遍历判断j-i<=k && Math.abs(nums[j] - nums[i]) <= t,存在这种情况直接return true

var containsNearbyAlmostDuplicate = function(nums, k, t) {
    var len = nums.length;
    for(var i =0;i<len;i++){
        for(var j = i+1;j<len;j++){
            if(j-i<=k && Math.abs(nums[j] - nums[i]) <= t){
               return true
            }
        }
    }
    return false
};

方法二

  1. Math.abs(i-j)<=t,因此可以将数字放入若干大小为t+1的桶中
  2. 举例来说,将从0到t的数字放入编号为0的桶中,从t+1到2t+1的数字放入编号为1桶中,依此类推
  3. 如果两个数字被放入同人个桶中,那么它们的差的绝对值一定小于或等于t
  4. 具体逐一扫描数组中的数字,如果当前扫描的数字num,那么它将放入编号为id的桶中,如果这个桶中之前已经有数字,那么就找到两个差的绝对值小于或等于t的数字
  5. 如果桶中之前没有数字,则再判断编号为id-1和id-2的这两个相邻的桶中是否存在与num的差的绝对值小于或等于t的数字
  6. 因为其它桶中的数字与num的差的绝对值一定大于t,所以不需要判断其他的桶中是否有符合条件的数字
var containsNearbyAlmostDuplicate = function (nums, k, t) {
  var buckets = new Map();
  var bucketSize = t + 1;
  var getBucketId = (num, bucketSize) => {
    return num >= 0
      ? Math.floor(num / bucketSize)
      : Math.floor((num + 1) / bucketSize) - 1;
  };
  for (var i = 0; i < nums.length; i++) {
    var num = nums[i];
    var id = getBucketId(num, bucketSize);
    if (
      buckets.has(id) ||
      (buckets.has(id - 1) && buckets.get(id - 1) + t >= num) ||
      (buckets.has(id + 1) && buckets.get(id + 1) - t <= num)
    ) {
      return true;
    }
    buckets.set(id, num);
    if (i >= k) {
      buckets.delete(getBucketId(nums[i - k], bucketSize));
    }
  }
  return false;
};