给定一个整数数组,判断是否存在重复元素。
如果任意一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true
解法一:暴力法
通过一个两层循环,遍历寻找重复元素。
有一个小小的改进,只需要在内层判断某一元素后面的元素即可,不需要每次都遍历全部的元素。
时间复杂度O(N^2),空间复杂度O(1)。
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
if (nums.size() == 1)
{
return false;
}
for (int i = 0; i < nums.size(); i++)
{
for (int j = 0; j < i; j++)
{
if (nums[i] == nums[j])
{
return true;
}
}
}
return false;
}
};
解法二:先排序
先对数组进行一次排序,然后对有序的数组进行一次遍历,依次判断相邻元素是否相同。
排序算法的复杂度最优是O(nlgn),空间复杂度O(N)/O(1),取决于排序算法。
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
if (nums.size() <= 1)
{
return false;
}
sort(nums.begin(), nums.end()); // 先排序
for (int i = 0; i < nums.size() - 1; i++)
{
if (nums[i] == nums[i + 1])
{
return true;
}
}
return false;
}
};
解法三:哈希表
用哈希表记录数组中的元素,如果有重复的可以O(1)时间内查询到。
时间复杂度:O(N),空间复杂度O(N)。
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
if (nums.size() <= 1)
{
return false;
}
unordered_map<int, int> res;
for (int i = 0; i < nums.size(); i++)
{
if (res.find(nums[i]) != res.end())
{
return true;
}
res.insert({nums[i], i});
}
return false;
}
};
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
示例 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
解法一:暴力法
通过二层循环,额外添加一个判断即可。
时间复杂度O(N^2),空间复杂度O(1)。
会超时。
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
for (int i = 0; i < nums.size(); i++)
{
for (int j = 0; j < i; j++)
{
if ((i - j) <= k && (nums[i] == nums[j]))
{
return true;
}
}
}
return false;
}
};
解法二:哈希Map方法
新建一个哈希Map,以数组的元素为key,下标为value。
遍历数组中的元素,如果map中存在,而且其value与数组的下标差小于k,则有重复的
否则插入新的数据。
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
if (nums.size() < 1)
{
return false;
}
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); i++)
{
if (map.count(nums[i]) != NULL && i - map[nums[i]] <= k)
{
return true;
}
map[nums[i]] = i;
}
return false;
}
};
解法三:Set方法
维护一个有K个元素的Set,里面不包含重复元素。
每次进行判断Set集合中是否有当前元素,有的话返回True。
插入元素。
如果Set中的元素超过了K个,就删除最前面的那个,始终维护Set中的大小为K。
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
unordered_set<int> st; // 设一个set为窗口
for (int i = 0; i < nums.size(); ++i) {
if (!st.insert(nums[i]).second) return true; // 插入失败说明重复 否则完成插入
if (st.size() == k + 1) st.erase(nums[i-k]); // 保证窗口长度<=k+1
}
return false;
}
};