[LeetCode] 存在重复元素

存在重复元素


217、存在重复元素

难度:Easy

题目描述:

给定一个整数数组,判断是否存在重复元素。

如果任意一值在数组中出现至少两次,函数返回 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)。

  • Your runtime beats 30.29 % of cpp submissions
  • Your memory usage beats 5.72 % of cpp submissions (19.7 MB)
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;
    }
};

219、存在重复元素-2

难度:Easy

题目描述:

给定一个整数数组和一个整数 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,则有重复的
否则插入新的数据。

  • Your runtime beats 41.57 % of cpp submissions
  • Your memory usage beats 5.55 % of cpp submissions (16 MB)
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;
    }
};

你可能感兴趣的:(LeetCode)