【算法】字符串转int类型思路及代码

简介: 【算法】字符串转int类型思路及代码

题目

给你一个字符串,如何这个字符串符合日常的整形的书写规范,那么我们需要写出将其转化为int类型的方法,并且不能使用Java提供的API,比如parseInt方法。

分析

这道题考察的其实就是parseInt的底层思路实现,相当于是你自己要学会写出一个parseInt方法。

并且考虑到需要将字符串转换为int,那么首先我们要保证,这个字符串符合int类型的格式,并且不会发生溢出。

有如下几种情况需要保证:

1:这个字符串可以为 ‘ - ’开头,但是不能只有一个 ‘ - ’

2:这个字符串开头为0时字符串长度必须也为1

3:不能发生溢出,也就是字符串的值不能大于 2147483647,不能小于 - 2147483648

4:字符串中不能出现除了 ‘ - ’,‘0’ - ‘9’的任何其他非法字符,比如 ‘A’

思路

1:我们可以先编写一个方法,判断这个字符串对应的数据是否符合它是一个数字类型的要求。

方法如下:

public static boolean isValid(String str) {
        char[] chars = str.toCharArray();
        //1:判断字符串不以 ‘ - ’开头并且也不是数字开头
        if (chars[0] != '-' && (chars[0] < '0' || chars[0] > '9') {
            return false;
        }
        //2:字符串以'-'开头,但是长度为1,或长度不为1,但是chars[1]='0'
        if (chars[0] == '-' && (chars.length == 1 || chars[1] == '0')) {
            return false;
        }
        //3:字符串以0开头,但是长度不为1
        if (chars[0] == '0' && chars.length != 1) {
            return false;
        }
        //4:判断字符串中是否有非法字符
        for (int i = 1; i < chars.length; i++) {
            if (chars[i] > '9' || chars[i] < '0') {
                return false;
            }
        }
        return true;
    }

2:成功判断当前字符串是否是一个合格的整形之后,我们开始具体的转换思路。

首先,根据字符串的正负进行判断,如果是以 ‘ - ’开头,那么从字符串的下标1处开始遍历,否则从0开始遍历。

然后,得到数据的方式其实就是,我们从字符串的左边开始遍历,当前值(初始为0)乘*10+当前位的值即可。

先看下面一段不考虑溢出的代码,你可能会这么写。

public static int parseInt(String str) {
        int cur = 0;
        int res = 0;
        boolean negative = str.charAt(0) == '-' ? true : false;
        for (int i = negative ? 1 : 0; i < str.length(); i++) {
            cur = str.charAt(i)-'0';
            res = res * 10+cur;
        }
        return negative?-1*res : res;
    }
    public static void main(String[] args) {
        System.out.println(parseInt("-123123"));
    }

对于不考虑溢出的情况,当然可以怎么写,答案也是对的,但是如果我们输入的字符串会溢出,那么我们处理起来会比较棘手,原因如下:

我们输入一个超出int范围的数据,那么就会溢出,从而导致数据的不准确。

可能你会认为加一个判断即可,但是很明显,在这里,如果我们在已经得到了最后的res之后进行判断,明显是不合理的,因为此时要么已经溢出,要么就是需要将long类型和int类型去比较,不太合理。

因此我们的解决思路是,得到 Integer.MAX_VALUE除以10的哪一个数据,然后这样子就能做到提前比较是否溢出。

代码如下:

public static int parseInt(String str) {
        int cur = 0;
        int res = 0;
        int maxQ = Integer.MAX_VALUE / 10;
        int maxP = Integer.MAX_VALUE % 10;
        boolean negative = str.charAt(0) == '-' ? true : false;
        for (int i = negative ? 1 : 0; i < str.length(); i++) {
            cur = str.charAt(i) - '0';
            //如果此时res已经大于了int最大值/10,并且此时cur还没有加上去就已经大于了,那么说明肯定溢出,直接返回0
            //如果等于,但是cur大于最后一位,那么也是溢出,也返回
            if (res > maxQ || (res == maxQ && cur > maxP) ||
                    (res == maxQ && negative && cur > maxP + 1)){
                return 0;
            }
            res = res * 10 + cur;
        }
        return negative ? -1 * res : res;
    }
    public static void main(String[] args) {
        System.out.println(parseInt("-2147483649")); // 0 
        System.out.println(parseInt("2147483649")); // 0 
    }

如下代码是Java的Integer提供的字符串转int类型的方法

public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        /*
         * WARNING: This method may be invoked early during VM initialization
         * before IntegerCache is initialized. Care must be taken to not use
         * the valueOf method.
         */
        if (s == null) {
            throw new NumberFormatException("null");
        }
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }
        int result = 0;
        boolean negative = false;
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;
        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+')
                    throw NumberFormatException.forInputString(s);
                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            while (i < len) {
                // Accumulating negatively avoids surprises near MAX_VALUE
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }

完整代码

package com.base.learn.string;
/**
 * @author: 张锦标
 * @date: 2023/5/25 9:57
 * ParseInt类
 */
public class ParseInt {
    public static boolean isValid(String str) {
        char[] chars = str.toCharArray();
        //1:判断字符串不以 ‘ - ’开头并且也不是数字开头
        if (chars[0] != '-' && (chars[0] < '0' || chars[0] > '9')) {
            return false;
        }
        //2:字符串以'-'开头,但是长度为1,或长度不为1,但是chars[1]='0'
        if (chars[0] == '-' && (chars.length == 1 || chars[1] == '0')) {
            return false;
        }
        //3:字符串以0开头,但是长度不为1
        if (chars[0] == '0' && chars.length != 1) {
            return false;
        }
        //4:判断字符串中是否有非法字符
        for (int i = 1; i < chars.length; i++) {
            if (chars[i] > '9' || chars[i] < '0') {
                return false;
            }
        }
        return true;
    }
    public static int parseInt(String str) {
        int cur = 0;
        int res = 0;
        int maxQ = Integer.MAX_VALUE / 10;
        int maxP = Integer.MAX_VALUE % 10;
        //如果此时res已经大于了int最大值/10,并且此时cur还没有加上去就已经大于了,
        // 那么说明肯定溢出,直接返回0
        //如果等于,但是cur大于最后一位,那么也是溢出,也返回
        boolean negative = str.charAt(0) == '-' ? true : false;
        for (int i = negative ? 1 : 0; i < str.length(); i++) {
            cur = str.charAt(i) - '0';
            if (res > maxQ || (res == maxQ && cur > maxP) ||
                    (res == maxQ && negative && cur > maxP + 1)){
                return 0;
            }
            res = res * 10 + cur;
        }
        return negative ? -1 * res : res;
    }
    public static void main(String[] args) {
        String s = "123asd";
        if (!isValid(s)){
            //do something
        }else{
            parseInt(s);
        }
    }
}


相关文章
|
5天前
|
算法
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
|
17天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
18 3
|
16天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
1月前
|
算法
两个字符串匹配出最长公共子序列算法
本文介绍了最长公共子序列(LCS)问题的算法实现,通过动态规划方法求解两个字符串的最长公共子序列,并提供了具体的编程实现细节和示例。
73 1
两个字符串匹配出最长公共子序列算法
|
29天前
|
存储 缓存 算法
如何通过优化算法和代码结构来提升易语言程序的执行效率?
如何通过优化算法和代码结构来提升易语言程序的执行效率?
|
30天前
|
搜索推荐
插入排序算法的讲解和代码
【10月更文挑战第12天】插入排序是一种基础的排序算法,理解和掌握它对于学习其他排序算法以及数据结构都具有重要意义。你可以通过实际操作和分析,进一步深入了解插入排序的特点和应用场景,以便在实际编程中更好地运用它。
|
1月前
|
Python
[oeasy]python036_数据类型有什么用_type_类型_int_str_查看帮助
本文回顾了Python中`ord()`和`chr()`函数的使用方法,强调了这两个函数互为逆运算:`ord()`通过字符找到对应的序号,`chr()`则通过序号找到对应的字符。文章详细解释了函数参数类型的重要性,即`ord()`需要字符串类型参数,而`chr()`需要整数类型参数。若参数类型错误,则会引发`TypeError`。此外,还介绍了如何使用`type()`函数查询参数类型,并通过示例展示了如何正确使用`ord()`和`chr()`进行转换。最后,强调了在函数调用时正确传递参数类型的重要性。
21 3
|
22天前
|
缓存 分布式计算 监控
优化算法和代码需要注意什么
【10月更文挑战第20天】优化算法和代码需要注意什么
16 0
|
1月前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
19 0
|
2月前
|
机器学习/深度学习 存储 算法
经典算法代码
这段代码展示了多个经典算法,包括:穷举法解决“百钱买百鸡”问题;递推法计算“猴子吃桃”问题;迭代法求解斐波那契数列及折纸高度超越珠峰的问题。同时,还提供了希尔排序算法实现及披萨票务订购系统和汉诺塔问题的链表存储解决方案。每部分通过具体案例解释了算法的应用场景与实现方法。
31 3