0%

【题解】P1553 数字反转(升级版)

原题链接:点我跳转

此题思维难度不大,考察选手对于细节的把控。

本题分为四种情况:

  • 整数

  • 浮点数

  • 分数

  • 百分数

看似情况很多,实则需要做的操作是一样的。都是 反转 + 去掉前导0 + 可能的要去掉中间的0 + 可能的要去掉后缀0

反转

使用双指针,交换 s[i]s[j] 的值即可。其中,\(1\leq i< j\leq N\)

去掉前导 0

换种思路,去掉前导 \(0\) 也可以从第一个不为 \(0\) 的地方开始输出。

去掉中间的 0

这里使用一种暴力的方法,就是把中间的 0 换成空格,最后不输出空格即可。

去掉后缀 0

从后向前遍历,找到第一个不为零的地址,把它的下一个值标记为结束符。


这样,就大致梳理好了思路,即可快乐地写代码了。

写完题解才发现这种方法挺麻烦的。

不要问我为什么不用 string,写 char 数组写习惯了。

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
#include <iostream>
#include <cstring>
const int N = 109;
int st;
char s[N];
void swap(char &a, char &b) { char t = a; a = b; b = t; }
void reverse(char *s, int st, int ed) {
int i = st, j = ed;
while (i < j) {
swap(s[i], s[j]);
i++, j--;
}
} // 反转
int find_st(char *s, int st, int ed) {
for (int i = st; i <= ed; i++)
if (s[i] != '0')
return i;
return 0;
}
void erase_ed(char *s) {
int i = strlen(s) - 1;
while (s[i--] == '0');
s[i+2] = '\0';
}
void erase_md(char *s, int st) {
int i = st;
while (s[i] == '0') s[i++] = ' ';
}
int main() {
scanf("%s", s);
int len = strlen(s);
if (strchr(s, '%') - s >= 0) {
reverse(s, 0, len-2);
st = find_st(s, 0, len-2);
} else if (strchr(s, '.') - s >= 0) {
int add = strchr(s, '.') - s;
reverse(s, 0, add-1);
st = find_st(s, 0, add-1);
reverse(s, add+1, len-1);
erase_ed(s);
if (s[strlen(s)-1] == '.')
s[strlen(s)] = '0';
} else if (strchr(s, '/') - s >= 0) {
int add = strchr(s, '/') - s;
reverse(s, 0, add-1);
st = find_st(s, 0, add-1);
reverse(s, add+1, len-1);
erase_md(s, add+1);
for (int i = st; s[i]; i++)
if (s[i] != ' ')
putchar(s[i]);
return 0;
} else {
reverse(s, 0, len-1);
st = find_st(s, 0, len-1);
}
printf("%s", s + st);
return 0;
}

其实用 string 应该会更简单亿点,直接 stringstream但些都写完了就懒得再写其他方法了。