Snap-to-string conversion integer (atoi)

Question Profile

Programming ideas

  • Fill in symbol information, data string information during string traversal.
  • Strongly convert to a valid number based on the symbol and the last string information.
  • To prevent crossing borders, direct data is stored and represented using long-type data.
  • Validity query.

Programming Implementation

programming

First version

    public int myAtoi(String s) {
        char[] chars = s.toCharArray();
        int sign = 1;
        StringBuilder numberBuilder = new StringBuilder();
        int i = 0;
        while (i < chars.length && chars[i] == ' ') {
            i++;
        }
        s = s.substring(i);
        if (s.charAt(0) == '-') {
            sign = -1;
            s = s.substring(1);
        } else if (s.charAt(0) == '+') {
            sign = 1;
            s = s.substring(1);
        }
        i = 0;
        while (i < s.length() && Character.isDigit(s.charAt(i))) {
            numberBuilder.append(s.charAt(i));
            i++;
        }
        String numberStr = numberBuilder.toString();
        if (numberStr.isEmpty()) {
            return 0;
        }
        long value = Long.valueOf(numberStr) * sign;
        if (value < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        if (value > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        return (int) value;


    }

AC Version

    public int myAtoi(String s) {
        char[] chars = s.toCharArray();
        int sign = 1;
        StringBuilder numberBuilder = new StringBuilder();
        int i = 0;
        while (i < chars.length && chars[i] == ' ') {
            i++;
        }
        s = s.substring(i);
        if (s.isEmpty()) {
            return 0;
        }
        if (s.charAt(0) == '-') {
            sign = -1;
            s = s.substring(1);
        } else if (s.charAt(0) == '+') {
            sign = 1;
            s = s.substring(1);
        }
        i = 0;
        while (i < s.length() && Character.isDigit(s.charAt(i))) {
            numberBuilder.append(s.charAt(i));
            i++;
        }
        String numberStr = numberBuilder.toString();
        if (numberStr.isEmpty()) {
            return 0;
        }

        i = 0;
        while (i < numberStr.length() && numberStr.charAt(i) == '0') {
            i++;
        }
        numberStr = numberStr.substring(i);
        if (numberStr.isEmpty()) {
            return 0;
        }
        if (numberStr.compareTo(String.valueOf(Long.MAX_VALUE)) > 0 || numberStr.length()>=20) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }
        long value = Long.valueOf(numberStr) * sign;
        if (value < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        if (value > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        return (int) value;


    }

AC Version Prefix Extraction Function - Use Existing Functions Without Efficiency

    public int myAtoi(String s) {

        int sign = 1;
        StringBuilder numberBuilder = new StringBuilder();
        int i = 0;
        s = removeStartPrefix(s, " ");
        s = s.substring(i);
        if (s.isEmpty()) {
            return 0;
        }
        if (s.charAt(0) == '-') {
            sign = -1;
            s = s.substring(1);
        } else if (s.charAt(0) == '+') {
            sign = 1;
            s = s.substring(1);
        }
        i = 0;
        while (i < s.length() && Character.isDigit(s.charAt(i))) {
            numberBuilder.append(s.charAt(i));
            i++;
        }
        String numberStr = numberBuilder.toString();
        if (numberStr.isEmpty()) {
            return 0;
        }


        String prefix = "0";
        numberStr = removeStartPrefix(numberStr, prefix);
        if (numberStr.isEmpty()) {
            return 0;
        }
        if (numberStr.compareTo(String.valueOf(Long.MAX_VALUE)) > 0 || numberStr.length()>=20) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }
        long value = Long.valueOf(numberStr) * sign;
        if (value < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        if (value > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        return (int) value;


    }

    private String removeStartPrefix(String numberStr, String prefix) {
        while (numberStr.startsWith(prefix)) {
            numberStr = numberStr.substring(1);
        }
        return numberStr;
    }

Problems encountered

Cross-border issues

_The problem with out-of-bounds is that memory overflow occurs when i++ is not executed while fetching all the digital data into the container numberBuilder.

_Then there is a code snippet that does not contain a check for length that results in a break, and the problem is as follows:

        i = 0;
        while (i < s.length() && Character.isDigit(s.charAt(i))) {
            numberBuilder.append(s.charAt(i));
            i++;
        }
        String numberStr = numberBuilder.toString();

Program cannot handle empty string of boundary conditions

No empty string was considered,**fetching charAt(0)** from an empty string threw an exception

This is because

    public int myAtoi(String s) {
        char[] chars = s.toCharArray();
        int sign = 1;
        StringBuilder numberBuilder = new StringBuilder();
        int i = 0;
        while (i < chars.length && chars[i] == ' ') {
            i++;
        }
        s = s.substring(i);
        
        if (s.isEmpty()) {
            return 0;
        }
        // If the incoming string s is empty, the bit 0 is not fetched, and s.charAt(0) throws an exception, so a return of 0 if s is empty was added earlier.
        if (s.charAt(0) == '-') {
            sign = -1;
            s = s.substring(1);
        } else if (s.charAt(0) == '+') {
            sign = 1;
            s = s.substring(1);
        }

Unable to process ** "20000000000000000"**

_In use of Long.parseLong's time, to determine if the number is out of bounds, is based on Long's longest 19 digits.

        if (numberStr.length()>=20) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }

Unable to process "00000-42a1234"

_After removing invalid leading zeros, returning to''may cause problems.

_Therefore, after removing the leading 0, the empty string is judged.

       i = 0;
        while (i < s.length() && Character.isDigit(s.charAt(i))) {
            numberBuilder.append(s.charAt(i));
            i++;
        }
        String numberStr = numberBuilder.toString();
        if (numberStr.isEmpty()) {
            return 0;
        }

        i = 0;
        while (i < chars.length && chars[i] == '0') {
            i++;
        }
        numberStr = numberStr.substring(i);
        if (numberStr.isEmpty()) {
            return 0;
        }
        if (numberStr.length()>=20) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }

Unable to process'-000000000000000000000000000000000000001'

Unable to process ** "20000000000000000"**

The previous process of processing this number is still not valid and the final modification procedure is as follows:

        i = 0;
        while (i < numberStr.length() && numberStr.charAt(i) == '0') {
            i++;
        }
        numberStr = numberStr.substring(i);
        if (numberStr.isEmpty()) {
            return 0;
        }
        if (numberStr.compareTo(String.valueOf(Long.MAX_VALUE)) > 0 || numberStr.length()>=20) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }
        long value = Long.valueOf(numberStr) * sign;
        if (value < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        if (value > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        return (int) value;

numberStr.compareTo(String.valueOf(Long.MAX_VALUE)) > 0 || numberStr.length()>=20

_This expression returns the maximum and minimum values of Integer by symbol when the length of comparison is >=20 by comparing strings. But compare 19 bits to Long. MAX_ The maximum value of VALUE is compared by strings before the comparison is finally completed.

summary

_The answer to the basic question of this topic is relatively simple, and the basic framework of the program is not complex, but in dealing with cross-border problems, leading 0 problems, there are really many pits. Leading 0 issues can be handled in the following ways:

while(str.startWith('0')) {
	str = str.substring(1);
}

_This is relatively simple, do not consider efficiency, at first, especially when programming topics, correctness is greater than efficiency.

_We refine the above method into a function and inline it, and the resulting code is as follows:See AC version prefix refining function - use existing function without efficiency

_From above, you can see that the memory consumption is 0.1M more, which is indifferent, and the correctness is much greater than the efficiency. Debugging takes a lot of time, so it is very important to sort out the basic process of the program, understand the input and output, and process the logic.

_The most important benefit of this program is the problem of comparing Long's maximum values.

_is not particularly entangled. It is very tired and the eyes are painful. Tomorrow I will go to Nanyang. Hope to be in a good mood.

Added by anto91 on Fri, 04 Feb 2022 19:43:28 +0200