• 数据结构与算法训练:第十七弹


    1. 知识点总结

    1h32min实现AC成就

    本次主要涉及到的知识点是字符串处理、简单贪心、并查集以及二叉搜索树的构建。

    题目难度知识点
    1112 Stucked Keyboard🎯字符串处理
    1113 Integer Set Partition🎯简单贪心
    1114 Family Property🎯🎯并查集
    1115 Counting Nodes in a Binary Search Tree🎯🎯二叉搜索树BST

    2. 分题题解

    2.1 1112 Stucked Keyboard

    不是很难但是思路不好的话解决起来会很麻烦。

    主要思路:

    • 因为出现的字符是{a-z}, {0-9} and _,于是在此先用函数getId将字符和对应id作简单映射
    • 假设所有键都是坏的,只要某个键连续出现的次数不能被k整除,则此键正常,用isOk标记
    • 输出结果的时候,对于坏键,每次跳跃k,好键每次跳跃1
    #include
    using namespace std;
    string str;
    string word;
    string sentence;
    bool isOk[40]={false};//保存是否是好的 
    bool isChecked[40]={false};//保存已经输出的"坏键" 
    int id,k;
    int getId(char a){
    	if(a<='z'&&a>='a'){
    		return a-'a';//0-25
    	}else if(a<='9'&&a>='0'){
    		return a-'0'+26;//26-35
    	}else{
    		return 36;
    	}
    }
    int main(){
    	scanf("%d",&k);
    	getchar();
    	getline(cin,str);
    	//检测某个字符是否每次出现都是k
    	int len=str.length(); 
    	int cnt=1;
    	str+=".";
    	for(int i=1;i<len+1;i++){
    		//更新计算连续字符 
    		if(str[i]==str[i-1]){
    			cnt++;
    		}else{
    			if(cnt%k!=0){
    				id=getId(str[i-1]);
    				isOk[id]=true;
    			}
    			cnt=1;
    		}
    	}
    	//统计出事的 
    	for(int i=0;i<len;){
    		id=getId(str[i]);
    		sentence+=str[i];
    		if(!isOk[id]){
    			if(!isChecked[id]){
    				printf("%c",str[i]);
    				isChecked[id]=true;
    			}
    			i+=k;
    			continue;
    		}else{
    			i++;
    		}
    	} 
    	printf("\n%s",sentence.c_str());
    	return 0;
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    2.2 1113 Integer Set Partition

    看完题目大概就可以得出简单从小到大排序,前N/2给Set2,其他给Set1可以使得Set1的和大于Set2最大化

    #include
    using namespace std;
    //最小化n1-n2 最大化S1-S2
    int N,n1,n2,sum1=0,sum2=0;
    vector<int>v; 
    int main(){
    	scanf("%d",&N);
    	v.resize(N);
    	for(int i=0;i<N;i++){
    		scanf("%d",&v[i]);
    	}
    	sort(v.begin(),v.end());
    	n2=N>>1;
    	n1=N-n2;
    	for(int i=0;i<n2;i++){
    		sum2+=v[i];
    	}
    	for(int i=n2;i<N;i++){
    		sum1+=v[i];
    	}
    	printf("%d %d",n1-n2,sum1-sum2);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2.3 1114 Family Property

    并查集模板,主要是需要另外开AE数组去存每个家族的财产信息以及最后输出的时候需要新建结构体排序。

    #include
    using namespace std;
    int N,id,fid,mid,k,e,a;
    vector<int>cids;
    int f[10000];
    int root[10000]={0};
    int E[10000]={0};
    int A[10000]={0};
    bool exist[10000]={false};
    const int maxn=9999;
    struct Node{
    	int id;
    	int sum;
    	double avg_e,avg_a;
    };
    vector<Node>ans;
    bool cmp(Node a,Node b){
    	if(a.avg_a!=b.avg_a){
    		return a.avg_a>b.avg_a;
    	}else{
    		return a.id<b.id;
    	}
    }
    int Find(int a){
    	int x=a;
    	while(a!=f[a]){
    		a=f[a];
    	}
    	while(x!=f[x]){
    		int temp=x;
    		x=f[x];
    		f[temp]=a;
    	}
    	return a;
    }
    void Union(int a,int b){
    	int fa=Find(a);
    	int fb=Find(b);
    	if(fa<fb){
    		f[fb]=fa;
    		root[fa]+=root[fb];
    		root[fb]=0;
    	}else if(fb<fa){
    		f[fa]=fb;
    		root[fb]+=root[fa];
    		root[fa]=0;
    	}
    }
    int main(){
    	scanf("%d",&N);
    	for(int i=0;i<=maxn;i++){
    		f[i]=i;
    		root[i]=1;
    	}
    	while(N--){
    		scanf("%d%d%d%d",&id,&fid,&mid,&k);
    		cids.resize(k);
    		for(int i=0;i<k;i++){
    			scanf("%d",&cids[i]);
    		}
    		scanf("%d%d",&e,&a);
    		//注册用户信息
    		exist[id]=true;
    		E[id]+=e; 
    		A[id]+=a;
    		//将信息融合
    		if(mid!=-1){
    			Union(id,mid);
    			exist[mid]=true;
    		} 
    		if(fid!=-1){
    			Union(id,fid);
    			exist[fid]=true;
    		}
    		for(int i=0;i<k;i++){
    			Union(id,cids[i]);
    			exist[cids[i]]=true;
    		}
    	}
    	for(int i=0;i<=maxn;i++){
    		if(exist[i]){
    			int r=Find(i);
    			if(i!=r){
    				E[r]+=E[i];
    				A[r]+=A[i];
    			}
    		}
    	}
    	Node temp;
    	for(int i=0;i<=maxn;i++){
    		if(exist[i]&&root[i]!=0){
    			temp.id=i;
    			temp.sum=root[i];
    			temp.avg_e=E[i]*1.0/root[i];
    			temp.avg_a=A[i]*1.0/root[i];
    			ans.push_back(temp);
    		}
    	}
    	sort(ans.begin(),ans.end(),cmp);
    	int len=ans.size();
    	printf("%d",len);
    	for(int i=0;i<len;i++){
    		printf("\n%04d %d %.3f %.3f",ans[i].id,ans[i].sum,ans[i].avg_e,ans[i].avg_a);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106

    2.4 1115 Counting Nodes in a Binary Search Tree

    思路:

    • 构建二叉搜索树:注意关于左孩子可以和根节点值一样
    • 层次遍历存储每一层的节点值
    • 最后输出倒数两层节点数大小
    #include
    using namespace std;
    int N,temp;
    struct Node{
    	int val;
    	Node*left=NULL;
    	Node*right=NULL;
    	int level;
    };
    void Insert(Node* &root,int val){
    	if(root==NULL){
    		root=new Node;
    		root->val=val;
    	}else{
    		if(val<=root->val){
    			Insert(root->left,val);
    		}else if(val>root->val){
    			Insert(root->right,val);
    		}
    	}
    	return;
    }
    int max_level=0;
    vector<vector<int> >nodes;
    void levelTravel(Node*root){
    	queue<Node*>q;
    	root->level=0;
    	q.push(root);
    	while(!q.empty()){
    		Node*top=q.front();
    		if(top->level>max_level){
    			max_level=top->level;
    		}
    		if(top->left!=NULL){
    			top->left->level=top->level+1;
    			q.push(top->left);
    		}
    		if(top->right!=NULL){
    			top->right->level=top->level+1;
    			q.push(top->right);
    		}
    		//printf("level:%d val:%d\n",top->level,top->val);
    		nodes[top->level].push_back(top->val); 
    		q.pop();
    	}
    }
    int main(){
    	scanf("%d",&N);
    	Node*root=NULL;
    	nodes.resize(N);
    	for(int i=0;i<N;i++){
    		scanf("%d",&temp);
    		Insert(root,temp);
    	}
    	levelTravel(root);
    	int n1=nodes[max_level].size();
    	int n2=nodes[max_level-1].size();
    	printf("%d + %d = %d",n1,n2,n1+n2);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    3. 参考资料

  • 相关阅读:
    vue播放报警音实现过程
    java计算机毕业设计高校多媒体设备运维管理系统服务端MyBatis+系统+LW文档+源码+调试部署
    高频单链表题
    康谋分享 | 自动驾驶联合仿真——功能模型接口FMI(三)
    Jmeter集成到jenkins
    408 | 【2016年】计算机统考真题 自用回顾知识点整理
    【Seata】深入解读分布式事务解决方案
    AWS SAA C003 #29
    生成包含10个随机字母或数字的字符串,然后统计每个字符的出现次数
    机器学习小白理解之一元线性回归
  • 原文地址:https://blog.csdn.net/qq_45751990/article/details/126330400