牛客刷题题目(容器篇)(自用)
栈
AB3 有效括号序列
给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。
数据范围:字符串长度 。要求:空间复杂度
,时间复杂度
。
bool isValid(string s) { // write code here stack<char> sta; int len = s.length(); for (int i = 0; i < len; i++) { if (s[i] == '(') sta.push(')'); else if (s[i] == '[') sta.push(']'); else if (s[i] == '{') sta.push('}'); else if (sta.empty()) // 要记得先判断是不是空的,也就是有没有top() return false; else if (s[i] == sta.top()) // 然后才能放心地写top() sta.pop(); else return false; } return sta.empty(); }
AB5 点击消除
牛牛拿到了一个字符串。他每次“点击”,可以把字符串中相邻两个相同字母消除,例如,字符串"abbc"点击后可以生成"ac"。但相同而不相邻、不相同的相邻字母都是不可以被消除的。牛牛想把字符串变得尽可能短。他想知道,当他点击了足够多次之后,字符串的最终形态是什么?
int main() { string s; stack<char> sta; string ans; cin >> s; for (int i = 0; i < s.size(); i++) { if (sta.empty()) sta.push(s[i]); //用top()之前判断一下empty() else if (sta.top() == s[i]) { sta.pop(); continue; } else sta.push(s[i]); } if (sta.empty()) cout << "0"; while (!sta.empty()) { ans.push_back(sta.top()); //string可以push_back,也可以+= sta.pop(); } reverse(ans.begin(),ans.end()); // reverse( BidirIt first, BidirIt last ); BidirIt指的是双向迭代器类型,如std::vector、std::list、std::deque 以及 std::string。 // while (!sta.empty()) { // ans += sta.top(); // sta.pop(); // } // reverse(ans.begin(), ans.end()); cout << ans; }
AB2 栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
- 0<=pushV.length == popV.length <=1000
- -1000<=pushV[i]<=1000
- pushV 的所有数字均不相同
bool IsPopOrder(vector<int>& pushV, vector<int>& popV) { // write code here stack<int> sta; auto idx_push = pushV.begin(); for (auto idx_pop = popV.begin(); idx_pop != popV.end(); ) { // 遍历popV if (*idx_pop == *idx_push) { //如果准备要push进来的刚好等于准备pop的,那就push完直接pop idx_pop++; idx_push++; } else if(*idx_pop != *idx_push){ //如果不等于,就先把准备push的放进一个中间栈sta里 sta.push(*idx_push); idx_push++; } else if(!sta.empty() && *idx_pop == sta.top()){ //如果sta.top()刚好等于准备pop的,那就pop掉 sta.pop(); idx_pop++; } } return sta.empty(); // 看看sta如果不空,那就是没有成功pop完 }
队列
AB8 【模板】循环队列
请你实现一个循环队列,该循环队列可利用的空间大小等于个int型变量的大小。操作:push x:将
加入到循环队列尾端。若循环队列已满,输出"full"(不含引号),否则不输出任何内容。保证
为int型整数。front:输出队首元素,队首不出队。若队列为空,输出"empty"(不含引号)。pop:输出队首元素,且队首出队。若队列为空,输出"empty"(不含引号)。
// 可以用结构体:一个数组,一个队首head,一个队尾rear,进行模拟 // 我这里直接用的vector int main() { int n, q, num; string s; cin >> n >> q; vector<int> que; for (int i = 1; i <= q; i++) { cin >> s; if (s == "push") { cin >> num; if (que.size() == n) { cout << "full" << endl; } else { que.push_back(num); } } else if (s == "front") { if (que.empty()) { cout << "empty" << endl; } else { cout << que[0] << endl; } } else if (s == "pop") { if (que.empty()) { cout << "empty" << endl; } else { cout << que[0] << endl; auto it = que.begin(); que.erase(it); } } } }
向量
vector<vector<int>> mat(m, vector<int>(n, 0)); // m行n列矩阵,初始化为0
链表
AB11 合并两个排序的链表
输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
数据范围: ,
要求:空间复杂度 ,时间复杂度
如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:
或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:
ListNode* Merge(ListNode* list1, ListNode* list2) { // write code here if (list1 == nullptr) // 记得先判断是否是空的的情况 return list2; else if (list2 == nullptr) return list1; ListNode* newhead = nullptr; // 返回newhead ListNode* current = nullptr; // 用current来编排合并后的链表 while (list1 != nullptr && list2 != nullptr) { if (list1->val <= list2->val) { if (newhead == nullptr) { newhead = current = list1; } else { current->next = list1; current = current->next; } list1 = list1->next; } else { if (newhead == nullptr) { newhead = current = list2; } else { current->next = list2; current = current->next; } list2 = list2->next; } } if (list1 == nullptr) { // 若list1已空,list2还剩一些元素 current->next = list2; } else { current->next = list1; } return newhead; }
哈希
HJ10 字符个数统计
对于给定的字符串,统计其中的 在
到
范围内的不同字符的个数。
备注:受限于输入,本题实际输入字符集为
码在
到
范围内的可见字符。您可以参阅下表获得其详细信息(您可能关注的内容是,这其中不包含空格、换行)。
string s; set<char> se; unordered_map<char, int> m; cin >> s; for (int i=0; i<s.size(); i++) { se.insert(s[i]); //重复的元素无法插入set,相当于会自己去重 } cout << se.size();
HJ3 明明的随机数
对于明明生成的
个
到
之间的随机整数,你需要帮助他完成以下任务:
删去重复的数字,即相同的数字只保留一个,把其余相同的数去掉;
然后再把这些数从小到大排序,按照排好的顺序输出。
你只需要输出最终的排序结果。
set<int> s; int n, a; cin >> n; for (int i=0; i<n; i++){ cin >> a; s.insert(a); } for (auto it = s.begin(); it!=s.end(); it++) { cout << *it << endl; }
HJ23 删除字符串中出现次数最少的字符
对于给定的仅由小写字母构成的字符串,删除字符串中出现次数最少的字符。输出删除后的字符串,字符串中其它字符保持原来的顺序。
特别地,若有多个字符出现的次数都最少,则把这些字符都删除。
unordered_map<char, int> m; string s; cin >> s; for (int i = 0; i < s.size(); i++) { //将出现次数存入map m[s[i]]++; } int min = 20; for (auto it=m.begin(); it!=m.end(); it++){ //比较map里的min min = (min<it->second)? min:it->second; } for (int i = 0; i < s.size(); i++){ if (m[s[i]]==min) { //如果是min,就跳过 continue; } cout << s[i]; }
HJ8 合并表记录
数据表记录包含表索引和数值,请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,随后按照索引值的大小从小到大依次输出。
map <int, int> m; for (int i = 0; i < n; i++) { cin >> x >> y; m[x] += y; // 熟悉哈希表操作 } for (auto i : m) { cout << i.first << ' ' << i.second << endl; // 熟悉哈希表操作 }
HJ68 成绩排序
对于给出的
位同学的姓名和成绩,根据输入要求,按成绩升序或降序排列
map<int, vector<string>> m; for (int i = 0; i < n; i++) { cin >> name >> score; m[score].push_back(name); // map是按照键来排序的,即这里的socre,并且是字典序 } for (auto it = m.begin(); it != m.end(); it++) { // 这样是从begin遍历到end for (auto it = m.rbegin(); it != m.rend(); it++) { // 这样换句话来说是从end遍历到begin,但我们不能那样写,会报错
HJ41 称砝码
对于给定的
种砝码,重量互不相等,依次为
,数量依次为
,
现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。特别地,称重重量包括
。
int main() { int n, m, x; vector<int> weight; vector<int> num; unordered_set<int> flag; cin >> n; for (int i = 0; i < n; i++) { cin >> m; weight.push_back(m); } for (int i = 0; i < n; i++) { cin >> x; num.push_back(x); } flag.insert(0); for (int idx = 0; idx < n; idx++) { for (int i = 1; i <= num[idx]; i++) { // i为选中的砝码数量 unordered_set<int> tmp (flag); // 为了不在迭代过程中随意改变迭代变量 for (auto it = tmp.begin(); it != tmp.end(); it++) { // 对于所有的flag里的w都让他们加上weight[idx] flag.insert(*it + weight[idx]); } } } cout << flag.size() << endl; }
其他
HJ101 排序
对于给出的
个整数组成的数组
,根据输入要求,按升序或降序排列后输出。
if (op==0) { sort(vec.begin(), vec.end()); // 升序 // sort随机访问迭代器容器都能用,如vector,deque,数组,如果是list, forward_list,则不能用std::sort,得用他自己的成员函数sort,例如:lst.sort();flst.sort(); // 另外,用sort对string排序的结果叫做按照 字典序 排序,从字符串的第一个字符开始逐个比较,直到找到第一个不同的位置,通过比较这个位置字符的字母表顺序得出字符串的大小,称为字典序比较。 } else { sort(vec.begin(), vec.end(), greater<int>()); // 降序 } for (int v:vec) { cout << v << ' '; }