给定一个字符串,将里面的数字提取出来。要注意空格、符号、int 数据越界、前导0。
Input: "4193 with words"
Output: 4193
Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.
思路:
题目其实不难,难点在于要考虑的注意事项太多,容易混乱。应对 int 越界,用 long long来存储;应对空格,分为初始空格与非初始空格,加一个flag即可判断,初始空格跳过,非初始空格结束循环;应对符号,存在 “+-12” 这种多个符号,还有单个符号与无符号,也用flag区分;应对前导0,如“ -000000123”,将其跳过即可,但要先更新flag,防止“ -000+123”这种情况。
int myAtoi(string str) { int n = str.size(), sign = 1, flag = 0; //flag记录正负号个数 long long ans = 0; for (int i = 0; i < n; i++) { if (str[i] == ' ' && flag == 0) continue; //初始空格跳过 else if (str[i] == '-' || str[i] == '+') { //处理符号 if (flag++ > 0) break; else sign = str[i] == '-' ? -1 : 1; //sign = 1 or -1 } else if (str[i] - '0' >= 0 && str[i] - '0' <= 9) { //处理数字 flag = 1; if (str[i] == '0' && ans == 0) continue; //前导0跳过 ans = ans * 10 + (str[i] - '0'); if (ans > INT_MAX) return sign == 1 ? INT_MAX : INT_MIN; //是否超过int范围 } else break; //非数字与符号 } return ans*sign; }
总结:
flag为什么如此重要,因为 “符号只能出现在数字之前,初始空格只能出现在符号与数字之前”,所以初始flag = 0,而访问符号或者数字后就改变了flag,则此时再遇到空格或者符号,就跳出循环了。
Java 版:
class Solution { public int myAtoi(String str) { str = str.strip(); long flag = 1, ans = 0; if(str == "") return 0; if(str.charAt(0) == '-'){ flag = -1; str = str.substring(1,str.length()); }else if(str.charAt(0) == '+'){ str = str.substring(1, str.length()); } for(int i = 0; i < str.length(); i++){ if(str.charAt(i) >= '0' && str.charAt(i) <= '9'){ ans = ans * 10 + (str.charAt(i) - '0'); if(ans > Integer.MAX_VALUE) break; //必须得在这儿进行剪枝判断,不然会超过 long 的范围,然后溢出变成负数 }else break; } ans *= flag; if(ans > Integer.MAX_VALUE) return Integer.MAX_VALUE; if(ans < Integer.MIN_VALUE) return Integer.MIN_VALUE; return (int)ans; } }