两道日常练习题:洛谷P1165日志分析 + 洛谷P1553 数字反转(升级版)

发布时间:2024年01月22日

两道题的代码我都会附着文字详解,并且会简洁说明一下思路:

先看第一套题目:

? ? 题干:

输入输出:?

?

数据范围:

??这很明显是一道栈的问题,我们只需要根据题意模拟即可,需要注意的是当输入的N,也就是操作数较大的时候,我们需要考虑一个问题就是怎样去输出当操作类型为2,也就是输出当前库中最大的货物重量,我一开始是直接写了一个线性枚举的函数在栈中去查找,如下:

#include<iostream>
using namespace std;
const int N=2e5+100;
int a[N],n,top;
int fine(int x[],int l){
	int ans=-1<<20;
	for(int i=1;i<=l;i++)
	ans=max(ans,x[i]);
	return ans;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int pd;
		cin>>pd;
		if(pd==0){
			int x;
			cin>>x;
			a[++top]=x;		
		}
		else if(pd==1){
			if(top!=0)
			--top;
		}
		else {
		if(top==0) cout<<"0"<<endl;
		else cout<<fine(a,top)<<endl;	
		}
	}
	return 0;
}

很明显当N很大的时候,使用枚举函数输出最大重量的货物会超时,这是一段66分的代码,所以我考虑一下优化并仔细阅读了一下题目,发现我们可以直接在n次操作的枚举的过程中去更新当前货物最重的值以及他对应的在栈中的位置,同时在源代码的基础上考虑当仓库为空的时候,不同操作应该怎么做,接下来看代码:

#include<iostream>
using namespace std;
const int N=2e5+100;//把N定义到最大数据范围以上
int a[N],n,top;//a数组存栈中元素,n代表了操作个数,top表示栈顶指针
int main(){
	cin>>n;
	int ans=0,t=-1;//这里的ans和t是当前栈中最重的货物以及对应a数组下标
	for(int i=1;i<=n;i++){
		int pd;
		cin>>pd;//操作类型
		if(pd==0){
			int x;
			cin>>x;
			a[++top]=x;
			if(x>ans){//更新ans
				ans=x;
				t=top;
			}		
		}
		else if(pd==1){
		 if(ans==a[top] && top>1){//如果删除的这个货物是原来栈中最重的货物并且删除了之后栈中仍存在货物
		 	ans=-1;
		 	for(int j=1;j<=top-1;j++){//在top的前面所有货物中找出最重的货物
		 		if(a[j]>ans){
		 			ans=a[j];
		 			t=j;
				 }
			 }
		 }
		else if(ans==a[top] && top==1){//如果栈中已经只剩下一个货物并即将被删除
		 	ans=0;//将ans重新定义为0
		 }
		 if(top>0) --top; //当仓库非空时栈顶指针减去1
		}
		else {
		cout<<ans<<endl;//当操作选项为2的时候输出当前仓库的最重货物	
		}
	}
	return 0;
}

接下来看第二题:

输入输出以及数据范围;

?对所输入的数据的保证:

这道题目的思路并不复杂,主要就是存在太多的细节,直接上代码吧:

?

#include<string>
#include<iostream>
using namespace std;
int main(){
    string s;
	cin>>s;//用一个字符串来存储输入
	int l=s.size();//字符串的长度
	bool pd=false;//判断这个输入的字符串对应是否是整数
	int t;//如果是非整数,t就用来记录出现符号v对应的位置下标
	char v;//如果不是整数判断对应的别的数据类型并记录对应符号
	for(int i=0;i<l;i++)//这里判断输入的是否为整数
	{
		if(s[i]=='.' || s[i]=='%' || s[i]=='/')
		{
		v=s[i];
		pd=true;
		t=i;
		break;
		}
		}
		if(!pd && s[0]=='0'){//特判当输入为整数0的时候
			cout<<s[0];
			return 0;
		}
	if(!pd){//当输入一个非0的整数的时候
		int b=0;//当出现首个非0元素的时候更新b为1
		for(int i=l-1;i>=0;i--)
		{
		if(s[i]!='0') b=1;//注意细节
		if(b==1)  cout<<s[i];
		}
		return 0;
	}
	else {//当输入不是整数
	char str[100];//用来记录t位置之前需要反转的数字
	for(int i=0;i<t;i++)
	str[i]=s[t-1-i];
	int p=0;	
	for(int i=0;i<t;i++){
	if(str[i]!='0') p=1;
	 if(p==1) cout<<str[i];//同样要等出现首个非0元才能开始输出
	 }
     //特判当符号前面数据为0的情况
	 if(v=='/' && s[0]=='0') cout<<0; 
	 if(v=='%' && s[0]=='0') cout<<0;
	 if(v=='.' && s[0]=='0') cout<<0; 
	cout<<v;
	if(v=='%') return 0;//当为百分数的时候,输出已经结束了
	else {//否则根据是分数还是小数进行输出
		if(v=='/'){
			int n=0;
	    for(int j=l-1;j>t;j--)
	    {
	    if(s[j]!='0') n=1;	
		if(n==1) cout<<s[j];	
	         }
	     }
	    else {
	    	bool ok=false;//用来判断小数的小数部分是否全部为0
	    	for(int j=l-1;j>t;j--)
	    	if(s[j]!='0') ok=true;
	    	if(!ok) cout<<0;//如果全部为0小数部分需要输出一个0
	        else{//否则正常进行反转
	        int q=t+1;
			while(s[q]=='0') ++q; 	
			for(int j=l-1;j>=q;j--){
				cout<<s[j];
			}
			}	
		}     
   }
	}
	return 0;		
}

代码较长不过思路不复杂并且非常详细易懂考虑进了所有的情况,希望读者能够耐心看完。

谢谢观看,希望对你有所帮助!

文章来源:https://blog.csdn.net/2301_80050923/article/details/135738720
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。