LeetCode中字符串转换整数

109 阅读3分钟

LeetCode中字符串转换整数

在LeetCode中,字符串转换整数(String to Integer)是一个经典的算法题目。这个问题的基本思路是将一个字符串转换为相应的整数,如果字符串包含非数字字符,则返回0。此外,给定的字符串可能以“+”或“-”开头。

在这篇文章中,我们将解释如何使用Java解决这个问题,并提供一些示例和详细的代码实现。

  1. 判断前导空格

字符串转换整数的第一步是判断前导空格。这种情况下,我们可以使用Java内置的函数 trim(),它可以在字符串前和后删除所有空格。

示例:

String str = "    a  b c";
String trimmedStr = str.trim();
System.out.println(trimmedStr); // Output: "a b c"
  1. 判断正负号

接下来,我们需要判断字符串里面是否有一个正负号。如果有正负号,则将其作为字符串的第一个字符。如果字符串中没有这个符号,则默认为正数。

示例:

String str = "-42";
int sign = 1;
int start = 0;
if (str.charAt(0) == '-') {
    sign = -1;
    start++;
} else if (s.charAt(0) == '+') {
    start++;
}
  1. 计算数字

接下来,我们需要从字符串中提取数字并把它们相加起来。可以通过使用10进制的公式来实现。

示例:

String str = "  -42words  ";
int result = 0;
for (int i = start; i < str.length(); i++) {
    if (!Character.isDigit(str.charAt(i))) {
        break;
    }
    int digit = str.charAt(i) - '0';
    if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && digit > 7)) {
        return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
    }
    result = result * 10 + digit;
}
return sign * result;
  1. 完整代码示例
class Solution {
    public int myAtoi(String s) {
        int sign = 1;
        int start = 0;
        int result = 0;

        // 判断前导空格
        s = s.trim();

        // 判断正负号
        if (s.charAt(0) == '-') {
            sign = -1;
            start++;
        } else if (s.charAt(0) == '+') {
            start++;
        }

        // 计算数字
        for (int i = start; i < s.length(); i++) {
            if (!Character.isDigit(s.charAt(i))) {
                break;
            }
            int digit = s.charAt(i) - '0';
            if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && digit > 7)) {
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            result = result * 10 + digit;
        }
        return sign * result;
    }
}

其他实现方式 ,优秀的代码示例:

class Solution {
    public int myAtoi(String s) {
        int sign = 1, len = s.length(), i = 0, ans = 0;
        while (i < len && s.charAt(i) == ' ') ++i;
        if (i < len && (s.charAt(i) == '+' || s.charAt(i) == '-')) {
            sign = s.charAt(i++) == '+' ? 1 : -1;
        }
        while (i < len && Character.isDigit(s.charAt(i))) {
            int digit = s.charAt(i++) - '0';
            if (ans > (Integer.MAX_VALUE - digit) / 10) {
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            ans = ans * 10 + digit;
        }
        return sign * ans;
    }
}

这段代码的思路与前面介绍的相同,但是它使用的是更简洁的代码逻辑和少量的变量。同时,它使用贪心算法并且避免了乘法运算,使得代码更为高效。

这里还有一个使用状态机(StateMachine)的Java代码示例:

class Solution {
    public int myAtoi(String s) {
        Automaton automaton = new Automaton();
        int length = s.length();
        for (int i = 0; i < length; ++i) {
            automaton.get(s.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)[getCol(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 getCol(char c) {
        if (c == ' ') {
            return 0;
        }
        if (c == '+' || c == '-') {
            return 1;
        }
        if (Character.isDigit(c)) {
            return 2;
        }
        return 3;
    }
}

这个算法实现从状态机的角度考虑字符串的内容。它的优点是代码简洁,易于理解,并且易于扩展。同时,它的缺点是算法的效率有点低,其空间复杂度较高。

  1. 总结

在这篇文章中,我们讨论了如何使用Java解决字符串转换整数这个问题,并提供了相应的示例和详细的代码实现。使用这些代码,可以快速解决类似的题目以及其他一些字符串处理问题。