【力扣】存在重复元素系列
Leetcode 0217 存在重复元素
题目描述:Leetcode 0217 存在重复元素
分析
-
本题的考点:哈希表。
-
依次遍历每个元素,判断当前遍历的元素是否在哈希表中存在,如果存在,说明存在重复元素,否则将该元素插入哈希表中。
-
如果遍历结束都没有发现重复元素,返回
false
即可。
代码
- C++
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
unordered_set<int> S;
for (int x : nums) {
if (S.count(x)) return true;
S.insert(x);
}
return false;
}
};
- Java
class Solution {
public boolean containsDuplicate(int[] nums) {
HashSet<Integer> S = new HashSet<>();
for (int x : nums) {
if (S.contains(x)) return true;
S.add(x);
}
return false;
}
}
时空复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),
n
为数组长度。 -
空间复杂度: O ( n ) O(n) O(n)。
Leetcode 0219 存在重复元素 II
分析
-
本题的考点:哈希表。
-
不同于Leetcode 0217 存在重复元素,LC217使用的是
set
,本题使用map
记录每个元素对应的下标,如果存在重复元素,判断当前考察元素x
的下标和hash[x]
之间的距离是否小于等于k
即可。
代码
- C++
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_map<int, int> hash; // (数据, 数据在数组中对应的下标)
for (int i = 0; i < nums.size(); i++) {
int x = nums[i];
if (hash.count(x) && i - hash[x] <= k) return true;
hash[x] = i;
}
return false;
}
};
- Java
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
HashMap<Integer, Integer> hash = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int x = nums[i];
if (hash.containsKey(x) && i - hash.get(x) <= k) return true;
hash.put(x, i);
}
return false;
}
}
时空复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),
n
为数组长度。 -
空间复杂度: O ( n ) O(n) O(n)。
Leetcode 0220 存在重复元素 III
分析
-
本题的考点:哈希表。
-
若存在
i、j
,且j < i
,有 a b s ( n u m s [ i ] − n u m s [ j ] ) ≤ t abs(nums[i] - nums[j]) \le t abs(nums[i]−nums[j])≤t,则有 − t ≤ n u m s [ j ] − n u m s [ i ] ≤ t -t \le nums[j] - nums[i] \le t −t≤nums[j]−nums[i]≤t,则有: n u m s [ i ] − t ≤ n u m s [ j ] ≤ n u m s [ i ] + t nums[i]-t \le nums[j] \le nums[i] + t nums[i]−t≤nums[j]≤nums[i]+t。 -
下面步骤中的
x
就是这里的nums[j]
。 -
本题分为如下三步:
(1)使用
C++
提供的multiset
来记录[i-k, i-1]
中连续k
个数字。(2)对于当前的
num[i]
,用multiset
中的lower_bound
找到multiset
中第一个大于等于nums[i] - t
的数字。(3)如果存在该数字
x
,且x <= nums[i] + t
,则返回true
。 -
对于
Java
而言,可以使用TreeSet
,使用ceiling(x)
返回大于等于x
的第一个数。
代码
- C++
class Solution {
public:
typedef long long LL;
bool containsNearbyAlmostDuplicate(vector<int> &nums, int k, int t) {
multiset<LL> S;
for (int i = 0; i < nums.size(); i++) {
LL x = (LL) nums[i] - t;
LL y = (LL) nums[i] + t;
if (S.lower_bound(x) != S.end() && *S.lower_bound(x) <= y) return true;
S.insert(nums[i]);
if (S.size() == k + 1) S.erase(S.find(nums[i - k]));
}
return false;
}
};
- Java
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
TreeSet<Long> S = new TreeSet<Long>();
for (int i = 0; i < nums.length; i++) {
long num1 = (long) nums[i] - t;
long num2 = (long) nums[i] + t;
if (S.ceiling(num1) != null && S.ceiling(num1) <= num2) return true;
S.add((long) nums[i]);
if (S.size() == k + 1) S.remove((long) nums[i - k]); // 保证滑动窗口长度始终为k,有k+1个元素
}
return false;
}
}
时空复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),
n
为数组长度。 -
空间复杂度: O ( k ) O(k) O(k)。