字符串问题:字符串中数字子串的求和
【题目】
给定一个字符串 str, 求其中全部数字串所代表的数字之和。
【要求】
- 忽略小数点,例如 “A1.3”,其中包含两个数字 1 和 3.
- 如果紧贴数字子串的左侧出现字符"-", 当连续出现的数量为奇数时,则数字视为负,连续出现的数量为偶数时,则数字视为正。比如,“A-1BC--12”, 其中包含数字 -1 和 12.
- 若字符串的长度为N,时间复杂度为 O(N), 额外空间复杂度为 O(1)
【举例】
str="A1CD2E33", 返回 36。
str="A-1B--2C--D6E", 返回7。
【解答】
解法的关键在于如何在从左到右遍历 str 时,准确收集每个数字并累加起来。
1. 生成三个变量,整型变量 res, 表示当前的累加和; 整型变量 num, 表示当前收集到的数字; 布尔型变量 posi, 表示如果把 num 累加到 res 中,num 是正还是负。初始时,res = 0, num = 0, posi = true。
2. 从左到右遍历 str, 假设遍历到 i 位置的字符 cha, 根据具体的 cha 有不同的处理:
- 如果 cha 为 ‘0’~‘9’,i 位置的值记为 cur, cur = cha - '0'. 例如字符串 str = "123", 当 cha = '1', cur = 1, num = 1; 当 cha = '2', cur = 2, num = 12 = 1*10+2; 当 cha = '3', cur = 3, num = 123 = 12*10+3, res = res + 123. 若字符串 str = "-123", 当 cha = '3', cur = 3, num = 123, res = res + (-123)
具体实现请参考下面代码中的 numSum 方法:
1 public class Main { 2 3 public static void main(String[] args) { 4 System.out.println(new Main().numSum("A1CD2E33"));//36 5 System.out.println(new Main().numSum("A-1B--2C--D6E"));//7 6 System.out.println(new Main().numSum("-A-1B--2C---D----6E--"));//7 7 } 8 9 public int numSum(String str){ 10 if(str == null || str.length() == 0) return 0; 11 char[] chs = str.toCharArray(); 12 int res = 0; //表示累积和 13 int num = 0; //表示当前位置收集到的数字 14 boolean posi = true; //表示收集到的数字是否为正, true 为正, false 为负 15 16 for(int i = 0, len = str.length(); i < len; i++){ 17 char ch = chs[i]; 18 if(ch >= '0' && ch <= '9'){//若当前字符为数字字符, 则继续收集 19 int cur = ch - '0'; 20 num = num * 10 + cur; 21 if(i == len-1){//若最后一个字符为数字字符, 则将 num 其累加到 res 22 res += posi? num : -num; 23 } 24 }else{//若遇到非数字字符, 则将 num 累加到 res 25 res += posi? num : -num; 26 num = 0; //将收集到的数值 num 累加后, 需要清空 27 if(ch == '-'){//若遇到负号'-', 则需要更改当前收集数字 num 的正负 28 if(i > 0 && chs[i-1] == '-'){ 29 posi = !posi; 30 }else{ 31 posi = false; 32 } 33 }else{//若遇到其他字符, 更改 num 为正 34 posi = true; 35 } 36 } 37 } 38 39 return res; 40 } 41 42 }