题目介绍

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数。

函数 myAtoi(string s) 的算法如下:

  1. 空格:读入字符串并丢弃无用的前导空格(" "
  2. 符号:检查下一个字符(假设还未到字符末尾)为 '-' 还是 '+'。如果两者都不存在,则假定结果为正。
  3. 转换:通过跳过前置零来读取该整数,直到遇到非数字字符或到达字符串的结尾。如果没有读取数字,则结果为0。
  4. 舍入:如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被舍入为 −231 ,大于 231 − 1 的整数应该被舍入为 231 − 1 。

返回整数作为最终结果。

示例 1:

输入:s = "42"

输出:42

解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。

带下划线线的字符是所读的内容,插入符号是当前读入位置。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"42"(读入 "42")
           ^

示例 2:

输入:s = " -042"

输出:-42

解释:

第 1 步:"   -042"(读入前导空格,但忽视掉)
            ^
第 2 步:"   -042"(读入 '-' 字符,所以结果应该是负数)
             ^
第 3 步:"   -042"(读入 "042",在结果中忽略前导零)
               ^

示例 3:

输入:s = "1337c0d3"

输出:1337

解释:

第 1 步:"1337c0d3"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"1337c0d3"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"1337c0d3"(读入 "1337";由于下一个字符不是一个数字,所以读入停止)
             ^

示例 4:

输入:s = "0-1"

输出:0

解释:

第 1 步:"0-1" (当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"0-1" (当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"0-1" (读入 "0";由于下一个字符不是一个数字,所以读入停止)
          ^

示例 5:

输入:s = "words and 987"

输出:0

解释:

读取在第一个非数字字符“w”处停止。

提示:

  • 0 <= s.length <= 200
  • s 由英文字母(大写和小写)、数字(0-9)、' ''+''-' 和 '.' 组成

完整代码

class Solution {
    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"});
    }};

    public void get(char c) {
        state = table.get(state)[get_col(c)];
        if ("in_number".equals(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;
        }
        if (c == '+' || c == '-') {
            return 1;
        }
        if (Character.isDigit(c)) {
            return 2;
        }
        return 3;
    }
}

 思路解析

1. 类 Solution

方法 myAtoi
  • 功能:将字符串转换为整数。
  • 参数str,表示输入的字符串。
  • 返回值:转换后的整数。

该方法首先创建一个 Automaton 对象,然后遍历字符串中的每个字符,调用 Automaton 对象的 get 方法进行处理。最后返回经过处理的整数结果。

2. 类 Automaton

成员变量
  • sign:表示正负号,默认为 1(正数)。
  • ans:存储转换后的整数结果。
  • state:表示当前状态,初始为 “start”。
  • table:状态转移表,用于根据当前状态和字符类型确定下一个状态。
方法 get
  • 功能:根据当前字符和状态,更新状态并处理整数转换。
  • 参数c,表示当前处理的字符。

该方法首先根据当前状态和字符类型,从状态转移表中获取下一个状态。然后根据下一个状态执行相应的操作:

  • 如果状态为 “in_number”,则将当前字符转换为整数并累加到 ans 中。同时,检查 ans 是否超出整数范围,并进行截断处理。
  • 如果状态为 “signed”,则根据字符是 ‘+’ 还是 ‘-’ 设置 sign 的值。
方法 get_col
  • 功能:根据字符类型返回对应的列索引。
  • 参数c,表示当前处理的字符。
  • 返回值:列索引,用于在状态转移表中查找下一个状态。

该方法根据字符类型返回对应的列索引:

  • 空格:返回 0
  • 正负号:返回 1
  • 数字:返回 2
  • 其他字符:返回 3

代码执行流程

  1. 创建 Automaton 对象,初始化状态为 “start”。
  2. 遍历输入字符串中的每个字符。
  3. 调用 Automaton 对象的 get 方法,根据当前字符和状态进行状态转移。
  4. 在状态转移过程中,如果遇到数字,则累加到 ans 中,并处理整数范围溢出。
  5. 如果遇到正负号,则设置 sign 的值。
  6. 遍历结束后,根据 sign 和 ans 计算最终结果并返回。

知识点精炼

  1. 字符串处理:掌握字符串的基本操作,如遍历和字符类型判断。
  2. 有限状态机:理解状态机的概念,能够根据不同输入进行状态转移。
  3. 符号识别:能够处理正负号,并影响最终结果的符号。
  4. 整数累加与范围控制:在累加过程中注意整数类型的范围限制,防止溢出。
  5. 映射表应用:利用哈希表实现状态转移逻辑,提高代码的可读性和效率

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部