从C语言到C++_26(set+map+multiset+multimap)力扣692+349+牛客_单词识别(下)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 从C语言到C++_26(set+map+multiset+multimap)力扣692+349+牛客_单词识别

从C语言到C++_26(set+map+multiset+multimap)力扣692+349+牛客_单词识别(中):https://developer.aliyun.com/article/1521954

stable_sort解析代码:

幸运的是algorithm里面有一个stable_sort,它是基于归并排序实现的,是稳定的,也就是仿函数里少写了一段:(下面代码stable_sort换成sort就不行)

class Solution {
public:
    struct Great
    {
        bool operator()(const pair<string,int>& kv1,const pair<string,int>& kv2) const
        {
            if(kv1.second > kv2.second) // 次数大的在前面
            {
                return true;
            }
            /*if(kv1.second == kv2.second && kv1.first < kv2.first)
            {
                return true;
            }*/
            return false;
        }
    };
 
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> countMap;
        for(const auto& str : words) // 统计次数
        {
            countMap[str]++;
        }
 
        vector<pair<string,int>> sortV(countMap.begin(),countMap.end());
        stable_sort(sortV.begin(),sortV.end(),Great());
 
        vector<string> v;
        for(int i = 0; i < k; ++i)
        {
            v.push_back(sortV[i].first);
        }
        return v;
    }
};

multimap解析代码:

这里可以用multimap 代替stable_sort 以用来排序,可以直接用库里的仿函数:

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string, int> countMap;
        for(const auto& str : words) // 统计次数
        {
            countMap[str]++;
        }
 
        multimap<int, string, greater<int>> sortMap;
        for(const auto& kv : countMap)
        {
            sortMap.insert(make_pair(kv.second,kv.first));
        }
 
        vector<string> v;
        multimap<int, string, greater<int>>::iterator it = sortMap.begin();
        for(int i = 0; i < k; ++i)
        {
            v.push_back(it->second);
            ++it;
        }
        return v;
    }
};

349. 两个数组的交集 - 力扣(LeetCode)

难度简单

给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

示例 1:

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

输出:[2]


示例 2:

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

输出:[9,4]

解释:[4,9] 也是可通过的


提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
 
    }
};

set解析代码:

如果两个数组是有序的,则可以使用双指针的方法得到两个数组的交集。

这里还需要去重,(库里还有一个去重的函数unique,加上sort也可以解决这题)

unique是不改变size的,所以很麻烦,用set(排序+去重)就是很好的选择:

两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,

如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,

输出到vector,然后两个指针右移。当至少有一个指针超出数组范围时,遍历结束。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        set<int> s1(nums1.begin(),nums1.end());
        set<int> s2(nums2.begin(),nums2.end());
 
        set<int>::iterator it1 = s1.begin();
        auto it2 = s2.begin();
 
        vector<int> v;
        while(it1 != s1.end() && it2 != s2.end())
        {
            if(*it1 > *it2)
            {
                ++it2;
            }
            else if(*it1 < *it2)
            {
                ++it1;
            }
            else
            {
                v.push_back(*it1); // 相等,进哪个都行
                ++it1;
                ++it2;
            }
        }
        return v;
    }
};

单词识别_牛客题霸_牛客网 (nowcoder.com)

中等  通过率:22.37%  时间限制:1秒  空间限制:32M

知识点 字符串 哈希

描述

输入一个英文句子,把句子中的单词(不区分大小写)按出现次数按从多到少把单词和次数在屏幕上输出来,次数一样的按照单词小写的字典序排序输出,要求能识别英文单词和句号。

输入描述:

输入为一行,由若干个单词和句号组成

输出描述:

输出格式参见样例。

示例1

输入:

A blockhouse is a small castle that has four openings through which to shoot.

输出:

a:2

blockhouse:1

castle:1

four:1

has:1

is:1

openings:1

shoot:1

small:1

that:1

through:1

to:1

which:1

#include <iostream>
using namespace std;
 
int main() {
    int a, b;
    while (cin >> a >> b) { // 注意 while 处理多个 case
        cout << a + b << endl;
    }
}
// 64 位输出请用 printf("%lld")

set解析代码:

1. 遍历语句字符串,从语句字符串中分离出单词

2. 每分离出一个单词,就将该单词插入到map中,map会自动统计该单词出现的次数

3. 将统计到的结果按照要求排序

4. 输出

注意:1. 统计单词时,要将单词的大小写统一,因为题目说不区分大小写,注意循环输入

     2. 利用set将统计的结果按照次数由大到小排序,如果次数一样按照字典序排序

     3. 输出排序之后的结果

#include <iostream>
using namespace std;
#include <map>
#include <set>
 
class Compare
{
public:
    bool operator()(const pair<string,int>& left, const pair<string,int>& right)
    {
        // 次数从大到小排序,如果次数相同,再按照单词字典序排序
        return left.second > right.second || left.first < right.first;
    }
};
 
int main()
{
    string s;
    while(getline(cin, s))
    {
        map<string, int> m;
        string temp;
        
        // 分割单词,采用map统计每个单词出现的次数
        for(size_t i = 0; i < s.size(); ++i)
        {
            if(s[i] == ' ' || s[i] == '.')
            {
                if(temp != "")// 一个单词解析结束
                {
                    m[temp]++;
                }
                temp = "";
            }
            else
            {
                temp += tolower(s[i]); // 题目说不区分大小写
            }
        }
        
        set<pair<string,int>, Compare> s;
        // 将map中的<单词,次数>放到set中,并按照次数升序,次数相同按照字典序规则排序
        for(auto& e : m)
        {
            s.insert(e);
        }
        for(auto& e : s) // 将统计到的结果按照要求输出
        {
            cout<<e.first<<":"<<e.second<<endl;
        }
    }
    return 0;
}

multimap解析代码:

#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
 
int main() 
{
    string str;
    map<string, int> countMap;
    while(getline(cin,str))
    {
        for(int i=0,j=0;i<str.size();i++)
        {
            if(str[i]==' '||str[i]=='.')
            {
                string t=str.substr(j,i-j);
                if(isupper(t[0]))
                {
                    t[0]=tolower(t[0]);
                }
                j=i+1;
                countMap[t]++;
            }
        }
    }
 
    multimap<int, string, greater<int>> sortMap;
    for(const auto& kv : countMap)
    {
        sortMap.insert(make_pair(kv.second,kv.first));
    }
 
    for(const auto& kv : sortMap)
    {
        cout << kv.second << ":" << kv.first << endl;
    }
 
    return 0;
}

5. 笔试选择题

1. 下列说法正确的是()

A.set中的某个元素值不能被直接修改

B.map和unordered_map都是C++11提供的关联式容器

C.因为map和set的底层数据结构相同,因此在实现时set底层实际存储的是<key, key>的键值对


D.map和multimap中都重载了[]运算符


2.下面关于set的说法正确的是()


A.set中一定不能存储键值对,只能存储key


B.set可以将序列中重复性的元素去除掉


C.set中不能存储对象,因为对象字段较多,没有办法比较


D.set默认是升序,因为其默认是按照大于的方式比较的


3. 下面关于map的说法正确的是()


A.map的查询效率是O(log_2N),因为其底层使用的是二叉搜索树


B.map的key和value的类型可以相同


C.map中的有序只能是升序,不能是降序


D.map中的key可以直接修改


4. 下面关于map和set说法错误的是()


A.map中存储的是键值对,set中只储存了key


B.map和set查询的时间复杂度都是O(log_2N)


C.map和set都重载了[]运算符


D.map和set底层都是使用红黑树实现的

答案:

1. A

A:正确,因为set要保证其有序,因此set中元素不能被直接修改,若要修改可以先删除,在插入


B:错误,map是C++98中已存在的,unordered_map是C++11中才有的


C:错误,map和set底层结构都是红黑树,而其底层红黑树在实现时并没有区分是存k模型还是KV 模型


D:错误,map中key是唯一的,每个key都有与之对应的value,经常需要通过key获取value,因此 map单重载了[ ]运算符, multimap中key是可以重复的,如果重载了[ ]运算符,给定 一个key时,就没有办法返回 value了,因此,multimap中没有重载[ ]运算符


2. B


 A:错误,set中可以存储键值对,实例化set时,将set中元素类型设置为pair即可


 B:正确,因为set中的key是不能重复的


 C:错误,set中任意类型元素都可以存储,存储对象时,需要用户提供比较规则


 D:错误,set默认是升序,正确,但是其内部默认不是按照大于比较,而是按照小于比较


3. B


A:错误,map的查询效率是O(log_2N)是正确的,但map的底层结构不是二叉搜索树,而是红黑树


B:正确,key和value的类型由用户自己设置,可以相同也可以不同,取决于应用场景需要


C:错误,map可以是升序,也可是降序,默认情况下是升序,如果需要降序,需要用户在实例化 map时指定比较规则


D:错误,map中key不能修改,因为如果修改了就不能保证红黑树的特性了,即有序


4. C


 A:正确,map和set的概念


 B:正确,因map和set的底层结构都是红黑树,而红黑树是近似的平衡二叉搜索树,故查询时间 复杂度为O(log_2N)


 C:错误,map中重载了[ ]运算符,因为其需要通过key获取value,set中没有


 D:正确

本篇完。

下一部分:AVL树的介绍和模拟实现,然后是红黑树。再就是set和map的模拟实现。

目录
相关文章
|
8天前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
14 5
|
2月前
|
存储 JavaScript 前端开发
Set、Map、WeakSet 和 WeakMap 的区别
在 JavaScript 中,Set 和 Map 用于存储唯一值和键值对,支持多种操作方法,如添加、删除和检查元素。WeakSet 和 WeakMap 则存储弱引用的对象,有助于防止内存泄漏,适合特定场景使用。
|
3月前
|
存储 Java API
【数据结构】map&set详解
本文详细介绍了Java集合框架中的Set系列和Map系列集合。Set系列包括HashSet(哈希表实现,无序且元素唯一)、LinkedHashSet(保持插入顺序的HashSet)、TreeSet(红黑树实现,自动排序)。Map系列为双列集合,键值一一对应,键不可重复,值可重复。文章还介绍了HashMap、LinkedHashMap、TreeMap的具体实现与应用场景,并提供了面试题示例,如随机链表复制、宝石与石头、前K个高频单词等问题的解决方案。
41 6
【数据结构】map&set详解
|
2月前
|
存储 缓存 Java
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
【用Java学习数据结构系列】HashMap与TreeMap的区别,以及Map与Set的关系
39 1
|
3月前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
38 5
|
3月前
|
存储 JavaScript 前端开发
js的map和set |21
js的map和set |21
|
3月前
|
存储 前端开发 API
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
4月前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
4月前
|
Java
【Java集合类面试二十二】、Map和Set有什么区别?
该CSDN博客文章讨论了Map和Set的区别,但提供的内容摘要并未直接解释这两种集合类型的差异。通常,Map是一种键值对集合,提供通过键快速检索值的能力,而Set是一个不允许重复元素的集合。
|
4月前
|
存储 JavaScript 前端开发
ES6新特性(四): Set 和 Map
ES6新特性(四): Set 和 Map