leetCode-存在重复元素|| 这六种解法你掌握了么

4,126 阅读2分钟

这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

前言

有人相爱,有人夜里开车看海,有人leetcode第一题都做不出来,由此可见,leetcode的题还是有分量的。今天我们就来会会它们

题目介绍

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [1,2,3,1], k = 3
输出:true

示例 2:

输入:nums = [1,0,1,1], k = 1
输出:true

示例 3:

输入:nums = [1,2,3,1,2,3], k = 2
输出:false

提示:

1 <= nums.length <= 105
-109 <= nums[i] <= 109
0 <= k <= 105

哈希表

思路

  • 首先定义一个空对象objjs中的对象就是基于哈希构建的)
  • 循环遍历数组nums,获取到下标对应的值
  • 判断当前循环的下标值是否存在对象obj
  • 如果不存在,那么就把当前循环的值作为当前循环的下标存入对象obj
  • 如果存在 那么判断当前索引的下标减去对象obj[当前循环的下标]对应的值(这个值是循环的下标)是否小于等于k,那么返回true,否则返回false

解法一

var containsNearbyDuplicate = function (nums, k) {
    const obj = {}
    for (let i = 0; i < nums.length; i++) {
        const item = nums[i]
        if (obj[item] > -1 && i - obj[item] <= k) {
            return true
        } else {
            obj[item] = i
        }
    }
    return false
}

解法二

var containsNearbyDuplicate = function (nums, k) {
    const map = Object.create(null)
    for (let i = 0; i < nums.length; i++) {
        const item = nums[i]
        if (map[item] > -1 && i - map[item] <= k) {
            return true
        }
        map[item] = i
    }
    return false
};

说明

  • 解法一解法二都利用了js对象的特性实现
  • 解法二的区别是使用Object.create(null)方法创建的对象
  • 解法一创建对象是通过对象字面量,他俩的区别,大家可以看我leetcode第一题解法三leetCode-俩数之和-4种解法

解法三

var containsNearbyDuplicate = function (nums, k) {
    const map = new Map()
    for (let i = 0; i < nums.length; i++) {
        const item = nums[i]
        if (map.has(item) && i - map.get(item) <= k) {
            return true
        }
        map.set(item, i)
    }
    return false
};

说明

  • 解法三本质也是利用了哈希表的原理实现的
  • 解法三则是通过es6Map方法实现的

滑动窗口

介绍

Sliding window algorithm is used to perform required operation on specific window size of given large buffer or array.

滑动窗口算法是在给定特定窗口大小的数组或字符串上执行要求的操作。

This technique shows how a nested for loop in few problems can be converted to single for loop and hence reducing the time complexity.

该技术可以将一部分问题中的嵌套循环转变为一个单循环,因此它可以减少时间复杂度。

简单来说,滑动窗口算法就是在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度,从而也达到降低了循环的嵌套深度。

思路

  • 首先定义一个空数组
  • 循环数组nums,判断当前下标是否大于k
  • 如果小于等于
    • 判断循环中的当前值在数组arr中是否存在
    • 如果存在
      • 则证明符合要求,返回true
    • 否则
      • 把当前值添加到数组arr中,进行下一次循环
  • 如果大于,那么就把数组的第0项删掉(这样数组的长度就固定了),继续执行后续操作

解法一

var containsNearbyDuplicate = function (nums, k) {
    const arr = []
    for (let i = 0; i < nums.length; i++) {
        if (i > k) {
            arr.shift()
        }
        if (arr.indexOf(nums[i]) !== -1) {
            return true
        }
        arr.push(nums[i])
    }
    return false
}

解法二

var containsNearbyDuplicate = function (nums, k) {
    const arr = new Set()
    for (let i = 0; i < nums.length; i++) {
        if (i > k) {
            arr.delete(nums[i-k-1])
        }
        if (arr.has(nums[i])) {
            return true
        }
        arr.add(nums[i])
    }
    return false
}

说明

  • 解法一利用了数组的特性
  • 解法二的思路其实和解法一是一样的,不过解法二采用的是es6Set数据结构

写在最后

  • 这篇文章虽然写的是存在重复元素的解法
  • 其中也涉及了一些js书写的注意点
  • 希望你也能收获满满