• 数据结构与算法复习:第三十三弹


    1. 知识点总结

    总结:……从后往前刷题是正确的,前面感觉比后面的难一点,套路题少了很多

    题目难度知识点
    1043 Is It a Binary Search Tree🎯🎯BST和镜像BST
    1044 Shopping in Mars🎯暴力
    1045 Favorite Color Stripe✨✨动态规划21/30

    2. 分题题解

    2.1 1043 Is It a Binary Search Tree

    这题的主要难点在于对于镜像的BST树,不仅是构建的时候排序需要按照降序排列in数组,还需要修改build函数中k的选取过程,如下面AC代码所示,镜像树在构建的时候,k是从大往小遍历的,这会导致在相等值切分的时候会出现左右子树分配问题,最终影响一个测试点被卡。

    #include
    using namespace std;
    vector<int>pre,in;
    int N;
    struct Node{
    	int val;
    	Node*left=NULL;
    	Node*right=NULL;
    };
    Node*root=NULL;
    bool canBuild=true;
    Node*build(int inL,int inR,int preL,int preR){
    	if(inL<0||preL<0||inR>=N||preR>=N||inL>inR||preL>preR){
    		return NULL;
    	}
    	Node*node=new Node;
    	node->val=pre[preL];
    	int k;
    	bool flag=false;
    	for(k=inL;k<=inR;k++){
    		if(in[k]==node->val){
    			flag=true;
    			break;
    		}
    	}
    	if(!flag){
    		canBuild=false;
    		return NULL;
    	}
    	int num=k-inL;
    	node->left=build(inL,k-1,preL+1,preL+num);
    	node->right=build(k+1,inR,preL+num+1,preR);
    	return node;
    }
    Node*build1(int inL,int inR,int preL,int preR){
    	if(inL<0||preL<0||inR>=N||preR>=N||inL>inR||preL>preR){
    		return NULL;
    	}
    	Node*node=new Node;
    	node->val=pre[preL];
    	int k;
    	bool flag=false;
    	for(k=inR;k>=inL;k--){
    		if(in[k]==node->val){
    			flag=true;
    			break;
    		}
    	}
    	if(!flag){
    		canBuild=false;
    		return NULL;
    	}
    	int num=k-inL;
    	node->left=build(inL,k-1,preL+1,preL+num);
    	node->right=build(k+1,inR,preL+num+1,preR);
    	return node;
    }
    bool flag=false;
    void postTravel(Node*root){
    	if(root==NULL){
    		return;
    	}else{
    		postTravel(root->left);
    		postTravel(root->right);
    		if(flag){
    			printf(" ");
    		}else{
    			flag=true;
    		}
    		printf("%d",root->val);
    	}
    }
    int main(){
    	scanf("%d",&N);
    	pre.resize(N);
    	for(int i=0;i<N;i++){
    		scanf("%d",&pre[i]);
    	}
    	in=pre;
    	sort(in.begin(),in.end());
    	root=build(0,N-1,0,N-1);
    	if(!canBuild){
    		sort(in.begin(),in.end(),greater<int>());
    		canBuild=true;
    		root=NULL;
    		root=build1(0,N-1,0,N-1);
    	}
    	if(canBuild){
    		printf("YES\n");
    		postTravel(root);
    	}else{
    		printf("NO");
    	}
    	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

    2.2 1044 Shopping in Mars

    这题暴力破解即可~每次ans_aans_b中存储当前的最优解的集合,当遇到更优解时清空上两个数组,同时更新min_def,加入新的ab

    #include
    using namespace std;
    int N,M;
    vector<int>v,pre_sum;
    vector<int>ans_a,ans_b;
    int min_def;
    int main(){
    	scanf("%d%d",&N,&M);
    	v.resize(N+1);
    	pre_sum.resize(N+1,0);
    	for(int i=1;i<=N;i++){
    		scanf("%d",&v[i]);
    		pre_sum[i]=v[i]+pre_sum[i-1];
    	}
    	min_def=pre_sum[N]-M;
    	for(int a=1;a<=N;a++){
    		if(pre_sum[N]-pre_sum[a]+v[a]<M){
    			break;
    		}
    		for(int b=a;b<=N;b++){
    			int temp=pre_sum[b]-pre_sum[a]+v[a];
    			if(temp<M){
    				continue;
    			}else{
    				temp-=M;
    			}
    			if(temp>min_def){
    				break;
    			}else if(temp<min_def){
    				min_def=temp;
    				ans_a.clear();
    				ans_b.clear();
    				ans_a.push_back(a);
    				ans_b.push_back(b);
    			}else{
    				ans_a.push_back(a);
    				ans_b.push_back(b);
    			}
    		}
    	}
    	for(int i=0;i<ans_a.size();i++){
    		printf("%d-%d\n",ans_a[i],ans_b[i]);
    	}
    	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

    2.3 1045 Favorite Color Stripe

    一开始用的时DFS,拿了19分,超时2个测试点,报错1个测试点

    后来想到的是找到最长公共子序列即可:于是想到DP中的LCS问题

    得分21/30,DP代码如下:

    #include
    using namespace std;
    int N,M,L;
    vector<int>f,v;
    int max_len=0;
    struct Node{
    	int val;
    	int cnt;
    };
    vector<Node>nodes(1);
    int len;
    int main(){
    	scanf("%d%d",&N,&M);
    	f.resize(M+1);
    	for(int i=1;i<=M;i++){
    		scanf("%d",&f[i]);
    	}
    	scanf("%d",&L);
    	v.resize(L);
    	int cnt;int temp;
    	for(int i=0;i<L;i++){
    		scanf("%d",&v[i]);
    		if(i){
    			if(v[i]==temp){
    				cnt++;
    			}else{
    				Node node;
    				node.val=temp;
    				node.cnt=cnt;
    				nodes.push_back(node);
    				cnt=1;
    				temp=v[i];
    			}
    		}else{
    			temp=v[0];
    			cnt=1;
    		}
    	}
    	Node node;
    	node.val=temp;
    	node.cnt=cnt;
    	nodes.push_back(node);
    	len=nodes.size()-1;
    	vector<vector<int> >dp(len+1,vector<int>(M+1,0));
    	//dp[i][j] 
    	for(int i=1;i<=len;i++){
    		for(int j=1;j<=M;j++){
    			if(nodes[i].val==f[j]){
    				dp[i][j]=dp[i-1][j-1]+nodes[i].cnt;
    			}else{
    				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    			}
    		}
    	} 
    	printf("%d",dp[len][M]);
    	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

    看了柳神的代码理了一下思路:

    • 首先,按照喜欢的颜色序列,因为序列中元素不重复,所以是突破口,可以为每一个最喜欢的颜色用它们在序列中对应的下标替代
    • 同时,不需要所有最喜欢的颜色都出现
      于是原问题通过坐标替换可以变成一个经典的求最长不下降子序列的问题

    AC代码如下

    #include
    using namespace std;
    int N,M,L,color,ans;
    vector<int>favorite,colors,strip; 
    int main(){
    	scanf("%d%d",&N,&M);
    	favorite.resize(M);
    	colors.resize(N+1);
    	for(int i=1;i<=M;i++){
    		scanf("%d",&color);
    		colors[color]=i;//喜欢颜色的序号 
    	}
    	scanf("%d",&L);
    	for(int i=0;i<L;i++){
    		scanf("%d",&color);
    		if(colors[color]>=1){
    			strip.push_back(colors[color]);
    		}
    	} 
    	int len=strip.size();
    	vector<int>dp(len,0);
    	//需要计算最长不下降子序列的长度
    	for(int i=0;i<len;i++){
    		dp[i]=1;
    		for(int j=0;j<i;j++){
    			if(strip[i]>=strip[j]){
    				dp[i]=max(dp[i],dp[j]+1);
    			}
    		}
    		ans=max(ans,dp[i]);
    	} 
    	printf("%d",ans);
    	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

    3. 参考资料

    1045. Favorite Color Stripe (30)-PAT甲级真题_柳婼的博客-CSDN博客

  • 相关阅读:
    低代码平台:打破数据孤岛的利器,推动企业数字化转型
    制作一个简单HTML静态网页(HTML+CSS)
    Controller返回JSON数据
    详解 PyTorch 中的 torch.repeat 函数
    小程序--本地存储API
    深入C++02:深入学习C++还必须掌握的基础
    后台交互-首页->与后台数据进行交互,wsx的使用
    css 实现导航菜单
    在矩池云使用安装AgentTuning
    全球与中国亚麻籽行业消费量调研及未来产销需求分析报告2022-2028年
  • 原文地址:https://blog.csdn.net/qq_45751990/article/details/126609800