字符串中数字子串的求和

时间:2023-01-04 17:20:20

题目:

给定一个字符串str,求其中全部数字串所代表的数字之和。

要求:

忽略小数点字符,如"A1.3",其中包含两个数字1和3;

如果紧贴数字子川的左侧出现字符"-",当连续出现的数量为奇数时,则数字视为负,偶数时,则数字视为正。如"A-1BC--12",其中包含数字为-1和12。

举例:

str="A1CD2E33",返回36;

str="A-1B--2C--D6E",返回7。

难度:

思路:(考虑问题不全面)

以前对于这种题目,惯用方法是嵌套循环,这样虽然也能实现,但时间复杂度就是O(n^2)数量级的,达不到练习的目的。

对于这种题目,对整个字符串进行遍历,在遍历的过程中对每个字符进行相应处理。

在循环遍历中,我分成三种情况讨论,一种是数字字符,一种是'-'字符,一种是其他情形;并对不同的情形做不同处理。

若是数字字符,对其进行数字识别;若是'-'字符,则对符号位取反;若是其他情形,则根据符号位决定数字的正负,将其累加,并将符号位和数字变量置零。

代码:

#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
getline(cin, str);
int len = str.size();
int i, sum = 0, num = 0, flag = 0;
for (i = 0; i < len; i++)
{
if (str[i] == '-')
flag = 1 - flag;
else if (isdigit(str[i]))
num = num * 10 + str[i] - '0';
else
{
if (flag)
num = -num;
sum += num;
flag = 0;
num = 0;
}
}
cout << sum << endl;
system("pause");
return 0;
}

本以为我考虑的比较全面了,但是查阅书本上的讲解,发现其实有很多疏漏。

如"-1-2-3",应该返回-6,但程序给出的结果是0。这就是没有考虑到'-'字符也是作为数字识别结束的标志;

而且对于边界问题,考虑的也不全面。So, this is not a good solution......

参考思路:

对字符串进行遍历,判断每个字符是数字字符还是非数字字符。

如果是数字字符,更新数字变量;如果是非数字字符,首先判断符号标志位确定正负,再累加,对数字变量置零;并判断给非数字字符是否为'-',如果该位字符是'-',则判断前一个字符是否也是'-',如果前一个是'-',则对符号标志位取反;若不是,则对符号标志位置一;如果该位字符不是‘-’,对符号标志位置零。

注意,对于最后一位是数字,则需要对其进行单独考虑。

参考代码:

#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
getline(cin, str);
int len = str.size();
int i, num = 0, sum = 0, flag = 0; // num为当前收集到的数字,sum为目前累加和,flag为当前收集到的数字是正是负
for (i = 0; i < len; i++)
{
if (isdigit(str[i]))
{
num = num * 10 + str[i] - '0';
if (i == len - 1)
{
if (flag)
num = -num;
sum += num;
}
}
else
{
if (flag)
num = -num;
sum += num;
num = 0;
if (str[i] == '-')
{
if (i - 1 >= 0 && str[i - 1] == '-') // 当前位是'-',判断前一位是否为'-'
flag = 1 - flag;
else
flag = 1;
}
else
flag = 0;
}
}
cout << sum << endl;
system("pause");
return 0;
}