+3道 第39场周赛题目
42.栈的压入、弹出序列
1.本题目算下来只有两种操作
(1)栈顶元素和弹出序列当前元素不匹配,继续压入(如果弹出更不匹配了)
(2)栈顶元素和弹出序列当前元素匹配,直接弹出栈顶元素(如果不弹,意味着要再弹出一些元素后才能得到该栈顶元素,必不正确)
2.代码中为什么是while循环而非if、只判断一次呢?
答:因为每弹出一个元素,我们的弹出序列移动到下一个元素,序列元素是新的,我们的栈顶元素也是新的!(因为弹出了旧的栈顶元素),如果只匹配一次,相当于跳过了当前栈顶元素、只将新压入栈的元素和弹出序列进行匹配!!
class Solution {
public:
bool isPopOrder(vector<int> pushV,vector<int> popV) {
if(pushV.size()!=popV.size()) return false;
stack<int> stk;
int i=0;
for(auto x:pushV){
stk.push(x);
while(stk.size()&&stk.top()==popV[i]){
stk.pop();
i++;
}
}
return stk.empty();
}
};
第39场周赛
4302 元素分类
没啥技巧,就是得仔细考虑……调试出了很多没有想到的情况,要细心。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n];
if(n==0){
cout<<0<<endl;
return 0;
}
for(int i=0;i<n;i++)
cin>>a[i];
if(n==1){
cout<<abs(a[0])<<endl;
return 0;
}
sort(a,a+n);//从小到大
int suma=0,sumb=0;
if(a[0]>=0){
for(int i=0;i<n;i++) sumb=sumb+a[i];
}
else if(a[n-1]<=0){
for(int i=0;i<n;i++) suma=suma+a[i];
}
else{
int i;
for(i=0;i<n-1&&a[i]<0;i++) suma=suma+a[i];
for(;i<n;i++) sumb=sumb+a[i];
}
cout<<sumb-suma<<endl;
return 0;
}
4303 链表
用到了之前学到的用map保存链表节点的技巧。
#include <bits/stdc++.h>
using namespace std;
struct Node{
string val;
Node *next;
Node(){
next=NULL;
}
};
map<string,Node *> lists; //保存所有的节点
vector<string> words;//保存所有的字符串
vector<string> listhead;//保存头节点,即链条数
int main()
{
int q;
cin>>q;
string h,e;
for(int i=0;i<q;i++){
cin>>h>>e;
if((find(words.begin(),words.end(),h)==words.end())&&(find(words.begin(),words.end(),e)==words.end())){
//当前2个字符串都没有出现过,一定是个新链表
Node *head=new Node();
head->val=h;
Node *tail=new Node();
tail->val=e;
head->next=tail;
words.push_back(h);
words.push_back(e);
lists[h]=head;
lists[e]=tail;
listhead.push_back(h);
}
else if((find(words.begin(),words.end(),h)!=words.end())&&(find(words.begin(),words.end(),e)==words.end())){
//开始字符串出现过,而结尾字符串未出现过,加入结尾
Node *tail=new Node();
tail->val=e;
lists[h]->next=tail;
words.push_back(e);
lists[e]=tail;
}
else if((find(words.begin(),words.end(),h)==words.end())&&(find(words.begin(),words.end(),e)!=words.end())){
//开始字符串未出现过,结尾字符串出现过,加入开头
Node *head=new Node();
head->val=h;
head->next=lists[e];
words.push_back(h);
lists[h]=head;
for(int i=0;i<listhead.size();i++){
if(listhead[i]==e){
listhead.erase(listhead.begin()+i);
listhead.push_back(h);
break;
}
}
}
}
cout<<listhead.size()<<endl;
for(int i=0;i<listhead.size();i++){
cout<<listhead[i]<<" ";
Node *p=lists[listhead[i]];
while(p->next!=NULL) p=p->next;
cout<<p->val<<endl;
}
return 0;
}
4304.字符串归类
属于并查集类题目。
find
函数是并查集模板,具体去看基础算法课。
// 并查集
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=200010;
int n;
int p[N];
int id[26];
char str[55];
int find(int x){
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) p[i]=i;//初始化每一个字符串属于一种
int res=n;
for(int i=1;i<=n;i++)
{
scanf("%s",str);
for(int j=0;str[j];j++){
int c=str[j]-'a';
if(id[c]){
if(find(id[c])!=find(i))
{
p[find(i)]=find(id[c]);
res--;
}
}
else id[c]=i;
}
}
cout<<res<<endl;
return 0;
}