机试课
一、枚举和模拟(下)
模拟问题——非线性数据结构map
map词典
对比vector、set学习
可以通过下标访问元素,下标可以是任意类型,元素也可以是任意类型
打破了之前[整数]的限制
这里的下标叫键(key),元素叫值(value),键和值的组合叫键值对(pair)
可以通过key找到value
本质是集合,内容是键值对
分类
同set类比,底层一样
与set区别:set内是单个元素的集合,map内是键值对的集合
头文件
#include <map>
#include <unordered_map>
从2个维度划分:①有序②是否允许重复(对于键)
有序 | 无序 | |
---|---|---|
不重复(对于键) | map | unordered_map |
可重复(对于键) | multimap | unordered_multimap |
unordered_map常用,时间开销小
构建:
两个参数,<键类型,值类型>
pair<char, int> pair1 = {‘w’, 0};//是map的基本元素
pair的函数,first提取键,second提取值
//构造
//char是键类型,int是值类型
map<char, int> map1;//有序——>省空间,不省时间 不重复
multimap<char, int> map2;//有序,可重复
unordered_map<char, int> map3;//无序,不重复 常用!!!!!时间开销小!!!
unordered_multimap<char, int> map4;//无序,可重复
//键值对
pair<char, int> pair1 = {'w', 0};//是map的基本元素
//pair的函数,first提取键,second提取值
printf("key = %c, value = %d", pair1.first, pair1.second);
增:
insert函数:只能插入键值对 ,用花括号括起来变成pair
//新增
//insert函数:只能插入键值对
map1.insert(pair1);
map1.insert({'w', 1}); //插入key为w的值,没有效果
map2.insert(pair1);
map2.insert({'w', 1});
//map2.insert({'o', 1});//用花括号括起来变成pair
删:
erase函数:参数只为键值(key)
//删除
//erase函数:参数只为键值
map1.erase('w'); //只删除1个键值对
map2.erase('w');//可以删除多个键值对
查:
1、遍历
迭代器
it指向键值对——>用first和second提取
it是个指针——>用->运算符
//查找
map<char, int> map1 = {
{'w',0},{'o',1},{'r',2},{'l',3},{'d',4}
};//初始化的map
//遍历:迭代器
map<char, int>::iterator it;
for(it = map1.begin(); it != map1.end(); it++){//end是尾后的位置,最后一个位置的后一个位置
printf("key = %c, value = %d\n", it->first, it->second);//it指向键值对——>用first和second提取,it是个指针——>用->运算符
}
//换成multimap
printf("\n");
multimap<char, int> map2 = {
{'w',0},{'o',1},{'r',2},{'l',3},{'d',4}
};
map2.insert({'o',5});
multimap<char, int>::iterator it2;
for(it2 = map2.begin(); it2 != map2.end(); it2++){//end是尾后的位置,最后一个位置的后一个位置
printf("key = %c, value = %d\n", it2->first, it2->second);//it指向键值对——>用first和second提取,it是个指针——>用->运算符
}
2、查找
(1)通过key找对应的value
找key为o对应的值——>方括号运算符map1[‘o’]
如果访问的键不存在,会新增一个键值对,键为查找的’a’,值为默认初始值0
multimap不支持方括号运算符:因为一个key对应多个值
<1>map
map<char, int> map1 = {
{'w',0},{'o',1},{'r',2},{'l',3},{'d',4}
};
//找key为o对应的值——>方括号运算符map1['o']
printf("value = %d\n", map1['o']);
//如果访问的键不存在,会新增一个键值对,键为查找的'a',值为默认初始值0
printf("value = %d\n", map1['a']);//查找结果为0,因为新增了键值对
<2>multimap
通过迭代器访问返回的一堆value
lower_bound(key):返回key对应的第一个值的位置
upper_bound(key):返回key对应的最后一个值的后一个位置
与begin,end的区别:begin、end是整个容器;lower_bound和upper_bound是key对应的值起始和终止位置
multimap<char, int> map2 = {
{'w',0},{'o',1},{'r',2},{'l',3},{'d',4}
};
map2.insert({'o',5});
multimap<char, int>::iterator it2;
for(it2 = map2.lower_bound('o'); it2 != map2.upper_bound('o'); it2++){
printf("key = %c, value = %d\n", it2->first, it2->second);
}
(2)如果不想新增,有才输出,没有报原因——>find函数或count函数
//如果不想新增,有才输出,没有报原因——>find函数或count函数
if(map1.find('a') == map1.end()){//说明a不存在
printf("key is not in map.\n");
}else{
printf("value = %d\n", map1['a']);
}
if(map1.find('o') == map1.end()){//说明a不存在
printf("key is not in map.\n");
}else{
printf("value = %d\n", map1['o']);
}
改:
方括号运算符+赋值操作
//5.修改
//方括号运算符+赋值操作
map1['o'] = 6;
printf("value = %d\n", map1['o']);
例题1、手机键盘※※(完全没思考)
思路:
使用2个map
第一个map:记录每个字母的输入时间
键为char表示按键a-z,值为int表示输入时间
第二个map:判断是否为同一个数字键上,是则增加等待时间
键为键为char表示按键a-z,值为int表示在哪个按键
//两个map
//每个字母需要花费的时间
map<char, int> inputTime = {
{'a',1},{'b',2},{'c',3},
{'d',1},{'e',2},{'f',3},
{'g',1},{'h',2},{'i',3},
{'j',1},{'k',2},{'l',3},
{'m',1},{'n',2},{'o',3},
{'p',1},{'q',2},{'r',3},{'s',4},
{'t',1},{'u',2},{'v',3},
{'w',1},{'x',2},{'y',3},{'z',4}
};
//每个字母在哪个按键
map<char, int> keyMap = {
{'a',2},{'b',2},{'c',2},
{'d',3},{'e',3},{'f',3},
{'g',4},{'h',4},{'i',4},
{'j',5},{'k',5},{'l',5},
{'m',6},{'n',6},{'o',6},
{'p',7},{'q',7},{'r',7},{'s',7},
{'t',8},{'u',8},{'v',8},
{'w',9},{'x',9},{'y',9},{'z',9}
};
关键点:用map把关键信息组织起来
易错点:
(1)向字符串数组写入时,不用加取地址符号,因为str本身就是指向数组的指针
while(scanf("%s",str) != EOF){//这里不用加取地址符号,因为str本身就是指向数组的指针
(2)
int lastKey = -1;//表示上一次的按键,-1表示之前没有输入
(3)查找用方括号运算符
if(keyMap[str[i]] == lastKey){
代码:
#include <stdio.h>
#include <map>
using namespace std;
int main(){
//两个map
//每个字母需要花费的时间
map<char, int> inputTime = {
{'a',1},{'b',2},{'c',3},
{'d',1},{'e',2},{'f',3},
{'g',1},{'h',2},{'i',3},
{'j',1},{'k',2},{'l',3},
{'m',1},{'n',2},{'o',3},
{'p',1},{'q',2},{'r',3},{'s',4},
{'t',1},{'u',2},{'v',3},
{'w',1},{'x',2},{'y',3},{'z',4}
};
//每个字母在哪个按键
map<char, int> keyMap = {
{'a',2},{'b',2},{'c',2},
{'d',3},{'e',3},{'f',3},
{'g',4},{'h',4},{'i',4},
{'j',5},{'k',5},{'l',5},
{'m',6},{'n',6},{'o',6},
{'p',7},{'q',7},{'r',7},{'s',7},
{'t',8},{'u',8},{'v',8},
{'w',9},{'x',9},{'y',9},{'z',9}
};
//读取字符串
char str[200];
while(scanf("%s",str) != EOF){//这里不用加取地址符号,因为str本身就是指向数组的指针
int lastKey = -1;//表示上一次的按键,-1表示之前没有输入
int totalTime = 0;//统计总时间
for(int i = 0; str[i] != '\0'; i++){//遍历字符串
//判断是否等待
if(keyMap[str[i]] == lastKey){//若本次与上次同一按键,则总时间+2!!!!!!!查找用方括号运算符
totalTime += 2;
}
totalTime += inputTime[str[i]];
lastKey = keyMap[str[i]];//更新上次按键
}
printf("%d\n", totalTime);
}
return 0;
}