LeetCode力扣第8题:字符串转换整数 (atoi) (使用DFA状态转移方法解答)

这一题可以通过自动机(DFA)的方法解答,DFA方法实际上就是通过状态转移的方式解答。

根据题目,我们可以把求解过程分为四个状态:

  • 初始状态 - start - 0

  • 符号状态 - sign - 1

  • 数字状态 - num - 2

  • 终止状态 - end - 3

将这四个状态分别记为0,1,2,3 。程序从初始状态0开始,当运行到终止状态3就停止。

从初始状态开始,遍历字符串s。读取到的字符有四种情况:空格、符号位、数字、其他字符。

在各个状态遇到这四种字符时:

  • 初始状态0

  • 遇到空格,则状态不变,直接读取下一个字符;

  • 遇到符号位,记录读取到的符号,并将状态切换为符号状态1;

  • 遇到数字,记录下数字,并将状态切换为数字状态2;

  • 遇到其他字符,将状态切换为终止状态3。

  • 符号状态1

  • 遇到空格,将状态切换为终止状态3;

  • 遇到符号位,将状态切换为终止状态3;(当s="+-12"时,输出应为0,所以碰到两个符号位要终止)

  • 遇到数字,记录下数字,并将状态切换为数字状态2;

  • 遇到其他字符,将状态切换为终止状态3。

  • 数字状态2

  • 遇到空格,将状态切换为终止状态3;

  • 遇到符号位,将状态切换为终止状态3;

  • 遇到数字,记录下数字,状态不变;

  • 遇到其他字符,将状态切换为终止状态3。

  • 终止状态3

  • 直接终止遍历,返回得到的结果。

因此,可以得到状态转移函数:

空格

符号位

数字

其他

0

初始start

0

1

2

3

1

符号sign

3

3

2

3

2

数字num

3

3

2

3

3

终止end

有了状态转移函数,我们就可以很轻松的写出解答过程:

下面是使用Python的解答:

class Solution:
    def myAtoi(self, s: str) -> int:
        """使用DFA方法实现atoi"""

        sign_dist = {'+':1, '-':-1} # 符号标识种子
        num_seed = '0123456789'     # 数字字符种子

        sign = 1    # 符号标识,1为正,-1为负
        status = 0  # 初始状态为0
        # 0-初始start  1-符号sign  2-数字num  3-终止end

        integer = 0 # 最终要返回的整数

        # 遍历字符串s
        for c in s:
            # 0-初始状态start 
            if status == 0:
                if c == ' ':
                    continue
                elif c == '+' or c == '-':
                    sign = sign_dist[c]
                    status = 1
                elif c in num_seed:
                    integer = 10*integer + int(c)
                    status = 2
                else:
                    status = 3
            
            # 1-符号状态sign
            elif status == 1:
                if c == ' ' or c == '+' or c == '-':
                    status = 3
                elif c in num_seed:
                    integer = 10*integer + int(c)
                    status = 2
                else:
                    status = 3

            # 2-数字状态num
            elif status == 2:
                if c == ' ' or c == '+' or c == '-':
                    status = 3
                elif c in num_seed:
                    integer = 10*integer + int(c)                   
                    # 判断是否越界,越界直接返回边界值
                    if integer * sign < -1 * 2**31:
                        return -1 * 2**31
                    elif integer * sign > 2**31 - 1:
                        return 2**31 - 1
                else:
                    status = 3

            # 3-终止状态end
            elif status == 3:
                break

        # 返回最终结果
        return integer * sign

下面是使用C++的解答过程:

class Solution {
public:
    int myAtoi(string s) {
        // 使用DFA实现atoi

        string sign_seed = "+-";    // 符号标识种子

        int sign = 1;         // 符号标识
        int status = 0;       // 初始状态为0
        // 0-初始start  1-符号sign  2-数字num  3-终止end

        long long integer = 0;// 最终要返回的整数

        // 遍历字符串s
        for(int i = 0; i < s.size(); i++){
            // 通过switch进入不同的状态
            switch(status){
            // 0-初始状态start
            case 0:
                if(s[i] == ' '){
                    break;
                }
                else if(s[i] == sign_seed[0]){
                    sign = 1;
                    status = 1;
                }
                else if(s[i] == sign_seed[1]){
                    sign = -1;
                    status = 1;
                }
                else if(s[i] >= '0' && s[i] <= '9'){
                    integer = 10 * integer + (s[i] - '0');
                    status = 2;
                }
                else{
                    status = 3;
                }
                break;

            // 1-符号状态sign
            case 1:
                if(s[i] == ' '){
                    status = 3;
                }
                else if(s[i] == sign_seed[0] || s[i] == sign_seed[1]){
                    status = 3;
                }
                else if(s[i] >= '0' && s[i] <= '9'){
                    integer = 10 * integer + (s[i] - '0');
                    status = 2;
                }
                else{
                    status = 3;
                }
                break;

            // 2-数字状态num
            case 2:
                if(s[i] == ' '){
                    status = 3;
                }
                else if(s[i] == sign_seed[0] || s[i] == sign_seed[1]){
                    status = 3;
                }
                else if(s[i] >= '0' && s[i] <= '9'){
                    integer = 10 * integer + (s[i] - '0');
                    // 判断是否越界,越界直接返回边界值
                    if(integer * sign > 2147483647){
                        return 2147483647;
                    }
                    else if(integer * sign < -2147483648){
                        return -2147483648;
                    }
                }
                else{
                    status = 3;
                }
                break;

            // 3-终止状态end
            case 3:
                break;
            }
            if(status == 3){
                break;
            }
        }

        return integer * sign;
    }
};

猜你喜欢

转载自blog.csdn.net/lyb06/article/details/129465915