或许你已经知道了问题的描述,不过这里再重复一遍,因为很羞赧的说:“这个问题,我栽了个大跟头!”(尽情嘲笑我吧!/(ㄒoㄒ)/~~)
一个整数1234与它倒序数4321和称之为相反数。现在的问题要求是:从控制台输入一个整数n (1 ≤ n ≤ 10 ^ 5),输出它的相反数。如1234,就输出1234 + 4321 = 5555。
既然待处理的值是一个整数,一个简单的想法是把输入的数用一个long
来存储(64位系统,int
是4个字节,是可以代表以上整数范围的,但考虑到32位系统,就使用长整型吧。)。再用一个long
来表达最终的结果值result
,在输入n后就把它加入到result
中。现在result
与最后的正确结果就缺少它的倒序数了。
因为我们不知道最终输入的n总共有几位,所以如果要取出n的每一位,就不得不让其依次除以100000、10000、1000、100、10。然后乘以最终的除数,并乘以分别的倍数1、10、100、1000、10000、100000。然后你就会发现,这个决定有一个Bug
,如果不是6位的数字,在进行10000、100000的倍乘时,会出现问题。所以要让这个方法可行的话,还要判断当前输入数字的位数。但是问题的本身真的有这么复杂吗?
重新审一下题,输入元是一个知道大小范围的整数,确切来说是知道位数的整数。这给我们透露了什么样的信息了?是的,使用字符串处理。因为从控制台输入的内容本质上都是字符串类型,然后在运行时,系统会自动匹配对应类型,比如将它作为int
或者string
存储。使用字符串带来的好处是问题的解决过程就是字符串的倒序和顺序的字符和,再将其转换成数字即可。一个简单的实现可以兑现为:
#include <iostream>
using namespace std;
int main() {
string str;
int zeroASCII = '0';
cin >> str;
for (int i = 0; i < str.length(); i ++) {
int noASCII = str[i];
int reNoASCII = str[str.length() - 1 - i];
int resultASCII = noASCII - zeroASCII + reNoASCII - zeroASCII;
cout << resultASCII;
}
cout << endl;
return 0;
}
算法的实现过程其实很简单,就是利用字符的ASCII
码的差值来实现字符的相加。在OC
中我们有现成的API
可以完成字符串转成int
,而其实它的底层实现或许就是通过这样的一个方式来转换的。真是高级的API
用多了,最基本的线性过程工作流竟都有点忘却了,这里记录一笔:好好自省
。算法和数据结构方面需要恶补,这种小白菜级别的问题都掉入了坑里,真是让人觉得汗颜!
面壁思过一百天中……
上述例程没有考虑到进位问题,在牛客网上只能通过40%的测试用例,以下是它的修订版本:
#include <iostream>
#include <stack>
using namespace std;
int main() {
string str;
stack<int> result;
int zeroASCII = '0';
unsigned short int carryFlag = 0;
cin >> str;
for (int i = int(str.length() - 1); i >= 0; i --) {
int noASCII = str[i];
int reNoASCII = str[str.length() - 1 - i];
int resultASCII = noASCII - zeroASCII + reNoASCII - zeroASCII + carryFlag;
if (i == 0) {
result.push(resultASCII);
} else {
carryFlag = resultASCII / 10;
result.push(resultASCII % 10);
}
}
int count = int(result.size());
for (int i = 0; i < count; i ++) {
cout << result.top();
result.pop();
}
cout << endl;
return 0;
}