LeetCode第八题(字符串转换整数)

418 阅读1分钟

逐位取余法(Java)

核心思想:  逐位遍历字符串的过程中,先去除字符串中的前导空格字符,再依次判断剩余各个字符,注意正负号,将得到每一位数字字符转换为数字,相乘10倍并累加,最后判断是否在给定范围,若超过范围,则固定为最大值或最小值( 取值范围是从-2147483648至2147483647(-231至231-1),包括-2147483648和2147483647)

class Solution {
    public int myAtoi(String s) {
        int res = 0;//保存结果
        int sign = 1;//确定结果的正负
        int start = 0;//字符串中首个非空格字符的下标
        while(start < s.length() && s.charAt(start) == ' ')//去除字符串中的前导空格
            start++;
        for(int i = start; i < s.length(); i++){
            if(s.charAt(i) == '+' || s.charAt(i) == '-'){
                if(i == start && s.charAt(i) == '+')//字符串中首个非空格字符是“+”
                    sign = 1;
                else if(i == start && s.charAt(i) == '-')//字符串中首个非空格字符是“-”
                    sign = -1;
                else
                    break;
            }
            //Character.isDigit(s.charAt(i));
            else if(s.charAt(i) >= '0' && s.charAt(i) <= '9'){
                int digit = s.charAt(i) - '0';
                //判断整数是否大于32位有符号整数的最大值
                if((sign * res) > (Integer.MAX_VALUE / 10) || ((sign * res) == (Integer.MAX_VALUE / 10) && digit > Integer.MAX_VALUE % 10)){
                    return Integer.MAX_VALUE;//固定为最大值
                }
                //判断整数是否小于32位有符号整数的最小值
                if((sign * res) < (Integer.MIN_VALUE / 10) || ((sign * res) == (Integer.MIN_VALUE / 10) && -digit < Integer.MIN_VALUE % 10))
                    return Integer.MIN_VALUE;//固定为最小值
                res = res * 10 + digit;//相乘10倍并累加
            }
            else
                break;
        }
        return sign * res;
    }
}

确定有限状态自动机(deterministic finite automation, DFA)(Java)

核心思想: 对于一个给定的属于该自动机的状态和一个属于该自动机字母表求和的字符,它都能根据事先给定的转移函数转移到下一个状态(这个状态可以是先前那个状态) image.png

image.png

class Solution {
    public int myAtoi(String s) {
        Automation automation = new Automation();
        for(int i = 0; i < s.length(); i++){
            automation.get(s.charAt(i));
            if("end".equals(automation.state))//如果状态为end,跳出循环
                break;
        }
        return (int)(automation.sign * automation.ans);
    }
}
class Automation{
    public int sign = 1;//正负号
    public long ans = 0;//保存结果(long类型是为了保存超出超出32位有符号整数范围的结果)
    public String state = "start";//自动机的状态
    
    private HashMap<String, String[]> map = new HashMap<String, String[]>() {{//匿名内部类初始化map
        //表格内容
        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 int stateChange(char ch){
        if(ch == ' ')
            return 0;
        else if(ch == '+' || ch == '-')
            return 1;
        else if(Character.isDigit(ch))
            return 2;
        else
            return 3;
    }

    //将数字字符转化为等值的数字
    public void get(char ch){
        state = map.get(state)[stateChange(ch)];//根据字符获取最新状态
        if("in_number".equals(state)){
            ans = ans * 10 + (ch - '0');//相乘10倍并累加
            ans = sign == 1? Math.min(ans,(long)Integer.MAX_VALUE) : Math.min(ans, -(long)Integer.MIN_VALUE);//若整数超出32位有符号整数的最值,则固定为最值
        }
        else if("signed".equals(state))
            sign = ch == '+'? 1 : -1;//根据字符获取结果的正负 
    }
}