【LeetCode】—— unordered_map/set的应用

一、重复N次的元素LeetCode961题

1.1 题目描述

在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次。
返回重复了 N 次的那个元素。
示例 1:

输入:[1,2,3,3]
输出:3

示例 2:

输入:[2,1,2,5,3,2]
输出:2

示例 3:

输入:[5,1,5,2,5,3,5,4]
输出:5

提示:

4 <= A.length <= 10000
0 <= A[i] < 10000
A.length 为偶数

1.2 解题思路

解法一:

  • 计数法,思路很简单,这里我们用到unordered_map,因为我们不需要对数据进行排序,因此用unordered_map效率更高,通过将每个数字出现的次数进行统计,unordered_map使用原来可以参考博客:unordered_map/set的使用, 统计次数之后,再遍历countmap查看是否有数字出现的次数大于等于N次,有则返回该数即可

解法二:

  • 也可使用unordered_set进行求解,算是基于解法一的一个优化,优化的依据在于:依据题意,有一个数字出现了N次,而其余数字都只出现了一次。所以重复出现的数字便是出现了N次的数字,我们只需遍历vector取得vector的数在unordered_set中进行插入,插入失败的数即为重复出现N次以上的数,这个方法有点取巧,不太建议使用,但是效率提高了很多。
1.3 代码实现

解法一:

class Solution {
public:
    int repeatedNTimes(vector<int>& A) {
        unordered_map<int,int> countmap;
        for(auto& e : A)
        {
            countmap[e]++;
        }
        
        for(auto& kv : countmap)
        {
            if(kv.second >= A.size()/2)
                return kv.first;
        }
        return 0;
    }
};

解法二:

class Solution {
public:
    int repeatedNTimes(vector<int>& A) {
        unordered_set<int> us;
        for (auto e: A) {
            auto ret = us.insert(e);
            if (ret.second == false)
                return e;
        }
        return -1;
    }
};

二、两句话中不常见的单词

2.1 题目描述

给定两个句子 A 和 B 。 (句子是一串由空格分隔的单词。每个单词仅由小写字母组成。)
如果一个单词在其中一个句子中只出现一次,在另一个句子中却没有出现,那么这个单词就是不常见的。返回所有不常用单词的列表。您可以按任何顺序返回列表。

示例 1:

输入:A = “this apple is sweet”, B = “this apple is sour”
输出:[“sweet”,“sour”]

示例 2:

输入:A = “apple apple”, B = “banana”
输出:[“banana”]

提示:

0 <= A.length <= 200
0 <= B.length <= 200
A 和 B 都只包含空格和小写字母。

2.2 解题思路
  • 通过find找到每个单词之间的空格以分隔每个单词,再使用substr取得每个单词,以此类推取得所有的单词并在countmap中统计每个单词出现的次数
  • 最后遍历一遍countmap找到只出现一次的单词放入之前创建的vector中,返回即可
    两句话中不常见的单词
2.3 代码实现
class Solution {
public:
    vector<string> uncommonFromSentences(string A, string B) {
        A += ' ';
        A += B; //将A B字符串进行连接
        
        unordered_map<string,int> countmap;
        vector<string> v;
        size_t start = 0;
        size_t pos = 0;
        do
        {
            pos = A.find(' ',start);
            countmap[A.substr(start,pos-start)]++;//去每个单词,并统计次数
            start = pos + 1;
        }while(pos < A.size());
        
        for(auto& kv : countmap)
        {
            if(kv.second == 1)
                v.push_back(kv.first);
        }
        return v;
    }
};

三、存在重复元素LeetCode217题

3.1题目描述

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

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

3.2 解题思路

解法一:

  • 用到unordered_map,同样是统计每个数出现的次数,之后再遍历一遍unordered_map若有元素出现超过一次说明存在重复元素,返回true,若没有就返回false

解法二:

  • 思路很简单,用到了unordered_set,其实和重复n次的元素的思路一样,遍历取得vector中的元素插入到unordered_set中,如果插入失败说明有重复的元素 ,返回true,若没有则返回false即可

解法三:

  • 这是这三种方法中效率最高的一个,思路也很简单,将vector数组中的元素进行排序,再两两比较,若有相同的两个元素,说明存在重复元素,返回true,否则返回false。
3.3 代码实现

解法一:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_map<int,int> countmap;
        for(auto& e : nums)
        {
            countmap[e]++;
        }
        
        for(auto& kv : countmap)
        {
            if(kv.second > 1)
                return true;
        }
        return false;
    }
};

解法二:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        unordered_set<int> us;
        for(auto& e:nums)
        {
            auto ret = us.insert(e);
            if(ret.second == false)
                return true;
        }
        return false;
    }
};

解法三:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        if(nums.empty())
            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;
    }
};

四、两个数组的交集LeetCode349题

4.1 题目描述

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]

说明:

输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。

4.2 解题思路
  • 首先通过unordered_set对两个数组进行去重,再遍历第一个数组,找第一个数组中的元素也在第二个数组中出现了的元素,放进创建的vector数组中,返回该vector就是两个数组的交集。
4.3 代码实现
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        //用unordered_set对nums1的元素去重
        unordered_set<int> s1;
        for(auto& e : nums1)
        {
            s1.insert(e);
        }
        //用unordered_set对nums2的元素去重
        unordered_set<int> s2;
        for(auto& e : nums2)
        {
            s2.insert(e);
        }
        
        vector<int> v;
       //遍历s1,如果s1中的某个元素在s2中出现,即为二者交集
        for(auto& e : s1)
        {
            if(s2.find(e) != s2.end())
                v.push_back(e);
        }
        return v;  
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值