8. String to Integer (atoi) (medium)
从这道题中学到了以下几点
- 对问题进行分解,比如zigzag可以分解为竖直向下排列和斜向上排列.本题是提取给定字符串中的数字,看要求可以得出合法的输入可能包含四部分,先考虑一般情况再考虑边界情况
- 一般情况: 空格+正负号+数字+字母
- 边界情况: 空字符串
- 解决方案: 遍历整个字符串,依次处理这四部分,如果存在相应的部分则进行对应的操作;如果没有某一部分那就跳过,当然了,没有数字可不行
- 遍历字符串时,索引经过了不同的部分,i在各个部分中自加,所以得用while循环
- 字符串是否为空,通过它的长度判断,不是null
- 细节处理过于冗余
- 判断数字时,如果碰到了不是数字的字符直接break即可,因为在判断数字的循环中,每次执行到最后都会存下最终的无符号数.我开始没有break,而是分不同的情况return,这样做就多余了
- 我判断溢出时分正负数判断,处理正负数的时候还出现了小错误.其实最简单的方法就是利用Integer.MAX_VALUE和Integer.MAX_VALUE之间的关系
- Integer.MAX_VALUE和Integer.MAX_VALUE的符号和个位数不同,其余位完全一样
- Integer.MAX_VALUE和Integer.MAX_VALUE的个位数只差1(本题没用上)
- if (num > Integer.MAX_VALUE / 10 || ( num == Integer.MAX_VALUE / 10 && curr > Integer.MAX_VALUE % 10) )
- 逻辑运算符的运算顺序: 与 大于 或
- 某个char是否为数字通过字符减法str.charAt(i) - '0'的大小判断,差∈[0,9]则是数字
public int myAtoi(String str) {
int n = str.length(),i = 0, sign = 1,num = 0;
//1. 这一部分处理空字符串
if (n == 0) return 0;
//2. 这一部分处理空格
while(i < n && str.charAt(i) == ' ') i++;
//3. 这一部分处理正负号,没有正负号则sign就是1
//3.1 如果i++放到判断里面,可能就无法自加了
//3.2 但是此处不一定需要i++,因为没有i++说明此处不是正负号,是不是数字还需要继续判断
if(i < n && (str.charAt(i) == '+' || str.charAt(i) == '-')) sign = str.charAt(i++) == '+'? 1:-1;
//4. 这一部分处理数字
while(i < n){
int curr = str.charAt(i) - '0';
//4.1 非数字,跳出循环
if (curr > 9 || curr < 0) break;
//冗余
//if ((curr > 9 || curr < 0) && num == 0) return 0;
//f ((curr > 9 || curr < 0) && num > 0) return num*sign; // 两处返回 num*sign,漏掉了sign
//4.2 检查是否溢出
//4.2.1 仅使用Integer.MAX_VALUE判断是否溢出,注意Integer.MAX_VALUE和Integer.MIN_VALUE 只有符号和个位数不同,其余位完全一样!
if (num > Integer.MAX_VALUE / 10 || ( num == Integer.MAX_VALUE / 10 && curr > Integer.MAX_VALUE % 10) )
return sign == 1? Integer.MAX_VALUE:Integer.MIN_VALUE;
//超级冗余
//判断溢出,得在循环里面提前判断,因为溢出就显示不了了
//Integer.MAX_VALUE , Integer.MIN_VALUE
//if(num*sign < Integer.MIN_VALUE / 10 ) return Integer.MIN_VALUE;
// 负数取模是负数!!!!!
//if((num*sign == Integer.MIN_VALUE / 10 ) && curr*sign < Integer.MIN_VALUE % 10) return Integer.MIN_VALUE;
//if(num*sign > Integer.MAX_VALUE / 10) return Integer.MAX_VALUE;
//if(Integer.MAX_VALUE / 10 == num*sign && curr*sign > Integer.MAX_VALUE % 10 ) return Integer.MAX_VALUE;
num = num*10 + curr;
i++;
}
return num*sign;
}