8. 字符串转换整数 (atoi) String to Integer
Implement atoi
which converts a string to an integer.
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned.
Note:
- Only the space character
' '
is considered a whitespace character. - Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range:
[−2^31, 2^31 − 1]
. If the numerical value is out of the range of representable values,2^31 − 1
or−2^31
is returned.
方法一:
自动机或有限状态机
我们的程序在每个时刻有一个状态 s,每次从序列中输入一个字符 c,并根据字符 c 转移到下一个状态 s'。这样,我们只需要建立一个覆盖所有情况的从 s 与 c 映射到 s' 的表格即可解决题目中的问题。
public int myAtoi(String str) { Automaton automaton = new Automaton(); int length = str.length(); for (int i = 0; i < length; i ++){ automaton.get(str.charAt(i)); } return (int)(automaton.sign*automaton.ans); } class Automaton{ public int sign = 1; public long ans = 0; private String state = "start"; private Map<String,String[]> table = new HashMap<String,String[]>(){{ put("start", new String[]{"start", "signed", "in_number", "end"}); put("signed", new String[]{"end", "end","in_number", "end"}); put("in_number", new String[]{"end", "end", "in_number", "end"}); put("end",new String[]{"end", "end", "end", "end"}); }}; private void get(char c){ state = table.get(state)[get_col(c)]; if ("in_number" == state){ ans = ans * 10 + c - '0'; ans = sign == 1 ? Math.min(ans, (long)Integer.MAX_VALUE) : Math.min(ans, -(long)Integer.MIN_VALUE); }else if("signed".equals(state)){ sign = c == '+' ? 1: -1; } } private int get_col(char c){ if (c == ' '){ return 0; }else if( c == '+' || c == '-'){ return 1; }else if( Character.isDigit(c)){ return 2; }else{ return 3; } } }
时间复杂度 O(n)
方法二:
顺序遍历。
先去掉空格,再去掉+-号,然后开始解析数字,注意溢出。
public int myAtoi(String str) { int len = str.length(); char[] charArray = str.toCharArray(); int index = 0; while (index < len && charArray[index] == ' ') { index++; } if (index == len) { return 0; } int sign = 1; char firstChar = charArray[index]; if (firstChar == '+') { index++; } else if (firstChar == '-') { index++; sign = -1; } int ans = 0; while (index < len) { char c = charArray[index]; if (c > '9' || c < '0') { break; } if (ans > Integer.MAX_VALUE / 10 || (ans == Integer.MAX_VALUE / 10 && (c - '0') > Integer.MAX_VALUE % 10)) { return Integer.MAX_VALUE; } if (ans < Integer.MIN_VALUE / 10 || (ans == Integer.MIN_VALUE / 10 && (c - '0') > -(Integer.MIN_VALUE % 10))) { return Integer.MIN_VALUE; } ans = ans * 10 + sign * (c - '0'); index++; } return ans; }
方法三:
正则表达式
public int myAtoi(String str) { String pattern = "^\\s*([+-]?\\d+)"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(str); if (!m.find( )) { return 0; } BigInteger ans = new BigInteger(m.group(1)); if(ans.compareTo(new BigInteger(String.valueOf(Integer.MIN_VALUE)))<0){ return Integer.MIN_VALUE; } if(ans.compareTo(new BigInteger(String.valueOf(Integer.MAX_VALUE)))>0){ return Integer.MAX_VALUE; } return ans.intValue(); }
参考链接
https://leetcode.com/problems/string-to-integer-atoi/
https://leetcode-cn.com/problems/string-to-integer-atoi