赞
踩
author:&Carlton
tags:模拟,字符串
topic:【NOIP】数字反转题解(含取整数各个位的常用算法思路)
language:C++
website:洛谷
date:2023年7月20日
目录
还是经典的数字取位,逐步取位并输出,利用输出顺序完成数字反转(即不依靠数组存储数值直接输出,简化步骤)
在这个过程一定要留意题目要求(也是模拟题的特点),区别正负数、去掉高位非法0。
下次注意的点:
①“%”运算符两侧需要int数据类型。pow函数返回值是double,与N参与四则运算也会是double,所以要先转换数据类型。
②pow函数在cmath或math.h头文件都可以。
③题意不要理解错了/漏了,写完算法可以具特殊例子先简单跑一下,看看符不符合要求,同时多考虑特殊情况,比如:区别正负数、去掉高位非法0(-32,100)
本题容易漏的点:
①非法0有可能由原数连续的低位0造成,都需要统一解决。
②负数最好一开始就转换为正数处理,不然每次运算得到的结果都会带有负号。
可以添加的优化:
对连续0的处理,在一开头就加上↓
while(N%10==0) N/=10;
吐槽一下:曲折,2次CE,3次WA,最后才AC,但其实蛮简单的,注意细节就好,而且一定要关注刚开始的算法设计环节,也要熟悉代码语法规则(多敲,多报错,从错误中学习hh)
源代码:
- #include <iostream>
- #include <cmath>//用到pow函数
- using namespace std;
-
- int main()
- {
- int N;
- cin >> N;
- int a,i;
- if(N==0)
- {
- cout << 0 << endl;
- return 0;
- }
- //是0直接打印0结束,不是那就继续运行程序
- else
- {
- if(N<0)
- {
- cout << '-'; //是负数就先打印负号,然后转换为正数处理
- N=-N;
- }
- for(i=0;N/(int)pow(10,i)!=0;i++) //%运算符两侧需要都为int类型
- {
- if(i==0 && N/(int)pow(10,i)%10==0)
- {
- do
- {
- i++;
- }while(N/(int)pow(10,i)%10==0);
- //防止打印非法首位0(要囊括原数低位连续0的情况,如100)
- }
- cout << N/(int)pow(10,i)%10; //注意没有endl干扰,每次只打印一个数据
- }
- //通过打印顺序来实现数字反转
- }
- return 0;
- }
一些思路:
①还是取位,但是结合运算后用数组存数,存的是一个整体,然后整体输出。
②通过抛数位、让位直接操作,十分快速(喜欢这类,很直接、方便):
- #include<iostream>
- using namespace std;
- int main()
- {
- int n; cin>>n; //反转之前的数
- if(n<0) {cout<<"-";n=-n;} //不管正负数,都转成正数方便操作。如果是负数,先输出一个"-"
- while(n%10==0) {n=n/10;} //如果一个数的最后一位为0,去掉不看
- int sum=0; //反转之后的数
- while(n!=0)
- {
- int k=n%10;
- sum=sum*10+k; //sum*10+k的意思是在原数sum的基础上拓展一个个位并存储k(有点像栈的操作)
- n=n/10; //去掉一位
- }
- cout<<sum<<endl;
- return 0;
- }
③还可以用字符串,输入的123不仅可以作为一个数字存在,也可以直接传入字符串类型:
利用字符串相关的运算法则和函数来解决问题(还没学,应该和重载运算符和字符串专题即常用字符串函数有关)
- #include<bits/stdc++.h>
- using namespace std;
- string s1,s2;
- int main(){
- cin>>s1;
- if(s1[0]=='-')
- {
- cout<<"-";//输出负号
- for(int i=s1.length()-1,j=0;i>=1;i--,j++) s2=s2+s1[i];//倒着变成正的
- if(s2[0]=='0') s2.erase(0,s2.find_first_not_of('0'));//去0
- cout<<s2;//输出
- }
- else //否则为正
- {
- for(int i=s1.length()-1,j=0;i>=0;i--,j++) s2=s2+s1[i];//正着倒序
- if(s2[0]=='0')s2.erase(0,s2.find_first_not_of('0'));//删除0
- cout<<s2;//输出
- }
- return 0;
- }
④栈,应该说的是一种编程思想,但本题解有结合字符串的使用。
- #include <bits/stdc++.h>
- using namespace std;
- char a[100001];
- int t=0;
- int main()
- {
- string b,c;
- bool sign=false,f=false;
- cin>>c;
- for(int i=0;i<=c.length();i++)
- {
- if(c[i]=='-') s=true;
- else a[++t]=c[i];
- }
- if(s==true) b+="-";
- t--;
- for(t;t>=0;t--)
- {
- if(a[t]!='0'&&f==false) f=true,b+=a[top];
- else if(f==true) b+=a[t];
- }
- int i=atoi(b.c_str());//字符串转换为整数
- cout<<i;
- return 0;
- }
①在处理取数位的问题时,好好利用“%”和“/”两个运算符,效率高。
②可以对输入的数据本身进行处理,这样更直接,不一定都得从侧面入手与输入的数据搭配,如果需要原始数据在开头保存就可以了:
比如我自己在循环体中用“N/(int)pow(10,i)!=0”作为判断条件,忽略了对数据本身直接处理能够更方便地得到有效数据,如优秀题解2的k,sum等。
也就是说我的题解还有个优化方向:用N=N/10代替pow函数来辅助完成取位操作。
欢迎指正与分享,谢谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。