ACwing 刷题 2022/3/18

在这里插入图片描述
+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 
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 
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 
#include 
#include 

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;
}

你可能感兴趣的:(ACwing,c++,算法,数据结构)