This article is participating in the “Java Theme Month – Java Brush questions punch card”, see the activity link for details

preface

The string conversion integer (AToi) is shown below:

MyAtoi (string s) converts a string to a 32-bit signed integer (similar to atoi in C/C++). MyAtoi (string s)

  • Read in the string and discard useless leading whitespace
  • Checks whether the next character (assuming it has not reached the end of the character) is a plus or minus sign and reads that character (if any). Determine whether the final result is negative or positive. If neither exists, the result is assumed to be positive.
  • Read the next character until the next non-numeric character is reached or the end of the input is reached. The rest of the string is ignored.
  • Convert the numbers read in the previous steps to integers (that is, “123” -> 123, “0032” -> 32). If no number is read in, the integer is 0. Change symbols as necessary (starting with Step 2).
  • If the number of integers exceeds the 32 – bit signed integer range[- 231, 231-1), you need to truncate the integer to keep it in the range. Specifically, integers less than −231 should be fixed to −231 and integers greater than 231 − 1 to 231 − 1.
  • Returns an integer as the final result.

Note:

Whitespace characters in this case include only the space character ‘ ‘. Do not omit any characters other than those following a leading space or number.

Example 1:

Example 2

Example 3

A, thinking

This is a long question, so you need to read the question several times. Write algorithm questions is to understand the meaning of the topic, and then combined with the data structure can be expressed

Read a string from left to right, taking consecutive digits (including ‘-‘ and ‘+’). Discard leading whitespace, continuing to the right

With a flow chart, it may be clear!

Second, the implementation

Since leading whitespace only appears before the string, to simplify the code, discard all leading whitespace before starting the loop and use a sliding window to find consecutive numeric strings

Variables are described as follows: left: indicates the left border of the window. Right: indicates the right border of the window. Flag: Indicates whether the value is positive

    public int myAtoi(String s) {
        // Discard all null characters
        int left = 0;
        int right;
        while (true) {
            // Return directly if the boundary is crossed
            if (left == s.length())
                return 0;
            if(s.charAt(left) ! =' ')
                break;
            left ++;
        }
        int flag = 1;
        / / plus
        if (s.charAt(left) == '+') {
            right = ++left;
        } else if (s.charAt(left) == The '-') {
            flag = -1;
            right = ++left;
        } else if(s.charAt(left) >= '0' && s.charAt(left) <= '9') {
            right = left + 1;
        } else {
            return 0;
        }
        // Extract as many numbers as possible
        while(right < s.length()) {
            if(s.charAt(right) < '0' || s.charAt(right) > '9') {
                break;
            }
            right ++;
        }
        // There are no numbers
        if (left == right)
            return 0;
        int ret = 0;
        for (char c : s.substring(left, right).toCharArray()){
            int temp = c-'0';
            // 10 * ret + temp < integer.max_value
            if (ret > (Integer.MAX_VALUE - temp )/10) {
                return flag == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            ret = ret * 10 + temp;
        }
        return ret * flag;
    }
Copy the code

The following information is displayed:

Three, how to improve

After seeing the AC code above, I don’t know if you will agree with me that it is too long and not concise. Even with comments, too much boundary judgment is a big project for later maintenance. So follow me to optimize the code above!

The most complex part of the code above is the many If/Else judgments, so how do you optimize this part? In Java, you can use state machines to solve complex processes and condition judgments.

Note the following points when writing to a state machine:

  • Define state
  • Define the action
  • State to state flow

Here is a reference to the state machine definition in the official solution

State machine description: there are four state lines: start, signed, in_number, and end. For example, start -> in_number indicates that the current state is start, and the state is changed to in_number because of the number read

In practical engineering, state machines usually use interfaces to define behavior. Implementation classes define states and implement interfaces.

    public int myAtoi(String str) {
        Automaton automaton = new Automaton();
        int length = str.length();
        for (int i = 0; i < length; ++i) {
            // End the loop prematurely
            if(! automaton.get(str.charAt(i))) {return (int) (automaton.sign * automaton.ans); }}return (int) (automaton.sign * automaton.ans);
    }
    
    /** * state machine */
class Automaton {
    public int sign = 1;
    public long ans = 0;
    // Initial state
    private String state = "start";
    // Define the state
    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 boolean get(char c) {
        boolean flag = true;
        // Next state
        state = table.get(state)[get_col(c)];
        if ("in_number".equals(state)) {
            ans = ans * 10 + c - '0';
            ans = sign == 1 ? Math.min(ans, Integer.MAX_VALUE) : Math.min(ans, -(long) Integer.MIN_VALUE);
        } else if ("signed".equals(state)) {
            sign = c == '+' ? 1 : -1;
        } else if ("end".equals(state)) {
            flag = false;
        }
        return flag;
    }

    // State flow
    private int get_col(char c) {
        if (c == ' ') {
            return 0;
        }
        if (c == '+' || c == The '-') {
            return 1;
        }
        if (Character.isDigit(c)) {
            return 2;
        }
        return 3; }}Copy the code

The following information is displayed:

Four,

You’ll notice that the state machine is slower than If/Else, so it’s a trade-off between maintainability and execution speed. For real projects, a good maintainability is often more important!

Today is the eighth question of the buckle ~ this series will update the 1-10 questions of the buckle for 10 consecutive days! Dig gold coin, I come 😁