字符串中的数字为结果的条件是:这个数字(包含符号)的前面只有空格
每次输入的字符包括四种情况:空格“ ”,符号“+/-”,数字,其他。
同时对应有四种状态:
-开始状态(start),即尚未读取到符号或者数字,只读取到空格或未读取
-符号状态(signed),即在开始状态下读取到一个符号
-拼数字状态(in_number),即在开始状态或者符号状态或者数字状态下又读取到一个数字
-结束状态(end),即已经读完数字或者在开始状态下即读取到非数字且非符号,或者符号状态读取到非数字。
状态转移表如下:
" " | +/- | number | other | |
---|---|---|---|---|
start | start | sighed | in_number | end |
signed | end | end | in_number | end |
in_number | end | end | in_number | end |
end | end | end | end | end |
class Solution {
public int myAtoi(String s) {
Automation automation = new Automation();
for (char c : s.toCharArray()) {
automation.get(c);
}
return (int) (automation.sign * automation.ans);
}
}
class Automation {
enum States{
START, SIGNED, IN_NUMBER, END;
}
public int sign = 1; // 结果的符号,如果读到有效的“-”,则变为-1
public long ans = 0; // 用于存放得到的结果,始终是正数,long类型为了防止结果溢出
private States state = States.START; // 表示状态,默认为开始状态
private Map table = new HashMap<>();
public Automation() {
// table 赋值,数组中对应输入分别为 空格“ ”,符号“+/-”,数字,其他 时的次状态
table.put(States.START, new States[] {States.START, States.SIGNED, States.IN_NUMBER, States.END});
table.put(States.SIGNED, new States[] {States.END, States.END, States.IN_NUMBER, States.END});
table.put(States.IN_NUMBER, new States[] {States.END, States.END, States.IN_NUMBER, States.END});
table.put(States.END, new States[] {States.END, States.END, States.END, States.END});
}
public void get(char c) {
// 根据当前状态和输入得到次状态
state = table.get(state)[getValue(c)];
// 只有次状态为数字或者符号的时候才会影响结果
if (state == States.IN_NUMBER) {
ans = ans * 10 + c - '0';
// 分正负结果分别处理结果溢出
if (sign == 1) {
ans = Math.min(ans, (long)Integer.MAX_VALUE);
} else {
ans = Math.min(ans, -(long)Integer.MIN_VALUE);
}
} else if (state == States.SIGNED) {
sign = c == '+' ? 1 : -1;
}
}
public int getValue(char c) {
if (c == ' ')
return 0;
if (c == '+' || c == '-')
return 1;
if (Character.isDigit(c))
return 2;
return 3;
}
}
先使用API去掉前导和尾部空白,对剩下的进行判断:
class Solution {
public int myAtoi(String s) {
String s1 = s.trim(); // 去掉s的前导和尾部空白
if (s1.length() < 1)
return 0;
long ans = 0; // long 类型防止溢出,恒为正值
int index = 0; // 当前下标
int sign = 1; // 符号
// s1 的首个字符三种可能
// 如果是+/-则修改符号,并下标右移
if (s1.charAt(index) == '+') {
sign = 1;
index ++;
} else if (s1.charAt(index) == '-') {
sign = -1;
index ++;
}
// 如果是数字或者其他
for (int i = index; i < s1.length(); i++) {
char c = s1.charAt(i);
// 如果是数字
if (Character.isDigit(c)) {
ans = ans * 10 + c - '0';
// 分类处理溢出
if (sign == 1) {
ans = Math.min(ans, Integer.MAX_VALUE);
} else {
ans = Math.min(ans,-(long)Integer.MIN_VALUE);
}
} else {
// 如果是其他则结束返回结果
break;
}
}
return (int) (sign * ans);
}
}