力扣刷题笔记,8. 字符串整数转换

针对力扣第8题,重点学习JAVA实现自动机的写法。

1.自动机

  字符串中的数字为结果的条件是:这个数字(包含符号)的前面只有空格
 每次输入的字符包括四种情况:空格“ ”,符号“+/-”,数字,其他。
同时对应有四种状态:
   -开始状态(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;
    }

}

2. 直接模拟

 先使用API去掉前导和尾部空白,对剩下的进行判断:

  1. 如果开始是数字,则合法,修改结果,指针进一继续判断;
  2. 如果开始是符号,则合法,修改结果符号,指针进一继续判断;
  • 如果是数字,则合法,修改结果,指针进一继续判断;
  • 如果是其他,则非法,结束;
  1. 如果是其他,则非法,结束。
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);
    }
}

你可能感兴趣的:(力扣刷题笔记,leetcode,算法,职场和发展)