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

简介: 从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的模拟实现。

目录
相关文章
|
4月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
324 1
|
7月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
555 1
|
4月前
|
存储 算法 容器
set_map的实现+set/map加持秒杀高频算法题锻炼算法思维
`set`基于红黑树实现,支持有序存储、自动去重,增删查效率为O(logN)。通过仿函数可自定义排序规则,配合空间配置器灵活管理内存。不支持修改元素值,迭代器失效需注意。`multiset`允许重复元素。常用于去重、排序及查找场景。
|
8月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
404 121
|
11月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
309 2
|
11月前
|
存储 算法 C++
【c++丨STL】map/multimap的使用
本文详细介绍了STL关联式容器中的`map`和`multimap`的使用方法。`map`基于红黑树实现,内部元素按键自动升序排列,存储键值对,支持通过键访问或修改值;而`multimap`允许存在重复键。文章从构造函数、迭代器、容量接口、元素访问接口、增删操作到其他操作接口全面解析了`map`的功能,并通过实例演示了如何用`map`统计字符串数组中各元素的出现次数。最后对比了`map`与`set`的区别,强调了`map`在处理键值关系时的优势。
607 73
|
8月前
|
存储 C++ 容器
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
370 0
|
8月前
|
编译器 C++ 容器
用一棵红黑树同时封装出map和set
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。
121 0
|
8月前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
306 0

热门文章

最新文章