每日算法 LeetCode 8

本文作者分享了自己在LeetCode上实现`myAtoi`函数的过程,详细阐述了代码逻辑,包括处理空格、符号、数字边界等细节,并对比了一位大佬简洁高效的代码实现,强调了`Character.isDigit`方法和巧妙的变量初始化。
摘要由CSDN通过智能技术生成

以下是我直接写的代码,就很无脑,想着先把前面可能出错的情况写出来,在判断数字出错的情况写出来,基本上很多细节想不到,都是在LeetCode上提交发现的。

细节太多,容易报空指针和数组越界异常,还有最无脑的就是算术异常,具体如何写出来的已经写在上面的code中。

 

/**
● 函数myAtoi(string s) 的算法如下:
●  
● 读入字符串并丢弃无用的前导空格
● 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
● 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
● 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
● 如果整数数超过 32 位有符号整数范围 [−2^31, 2^31− 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 2^31− 1 的整数应该被固定为 2^31− 1 。
● 返回整数作为最终结果。
● 注意:
●  
● 本题中的空白字符只包括空格字符 ' ' 。
● 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
●  
● 输入:s = "4193 with words"
● 输出:4193
● 解释:
● 第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
● ^
● 第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
● ^
● 第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
● ^
● 解析得到整数 4193 。
● 由于 "4193" 在范围 [-2^31, 2^31 - 1] 内,最终结果为 4193 。
●  
● //也就是说第一位要么+ / -
● //后面的是数字,继续加,不是数字 则返回零
● //不是数字,break
*/
class Solution {
    public int myAtoi(String s) {
        //读懂题意很重要,这个myAtoi,就是先判断第一个是什么符号,如果什么符号都没有,就是正的,如果不是数字也不是+ — 符号,则说明数字为零
        //而且此函数返回整形,小数点后面的也不用看了
        
        //先转成StringBuilder 对象,防止用String 占用内存空间,s.trim()顺便把前后空格删除
        StringBuilder sBuilder = new StringBuilder(s.trim());
        //用 i 来搞sBuilder的charAt()方法,获取字符串,特意做成一
        int i = 1;
        //判断正负
        int d = 0;
        //来截取长度
        int begin = 0;
        int distance = 0;
        
        //防止全是空格的情况<细节>
        if (sBuilder.toString().equals("")) return 0;
        //判断第一个符号是正还是负
        if (sBuilder.charAt(0) == '-') d++;
        //判断第一个是否为数字
        else if (sBuilder.charAt(0) >= '0' && sBuilder.charAt(0) <= '9') {
            begin++;//长度加一<细节>
        } else if (sBuilder.charAt(0) == '+') d = d;//这个好像只能这么搞了,去掉不行, 会跳到下一步<细节> +1返回零了
        else if (!(sBuilder.charAt(0) >= '0' && sBuilder.charAt(0) <= '9')) return 0;//如果第一个不是 + - (上面的条件不满足)或者 数字,直接返回零
        if(sBuilder.charAt(0) == '0' || sBuilder.charAt(0) == '+' || sBuilder.charAt(0) == '-') {
            //如果第一个满足上面条件,进入循环,保证数字不从0开始,Eg:000000002000000000<细节>
            //因为从零在下面也算长度 begin++
            while (i < sBuilder.length()) {//<细节>如果用sBuilder.charAt(i) == '0'直接判断,可能长度为1,下标就为零,空指针异常
                if (sBuilder.charAt(i) == '0') {
                    i++;
                } else {
                    break;
                }
            }
        }
        
        while (i < sBuilder.length()) {//遇到数组的时候,先判断长度!!!!!
            if ('0' <= sBuilder.charAt(i) && sBuilder.charAt(i) <= '9') {
                begin++;//计算长度
                distance = i;//记录数字截至的地方的后一位
                i++;
            } else {
                break;
            }
        }
        //如果 长度 长度没有增加,说明 i 在第一个循环到了 末尾都是零 ,所以直接返回零<细节>
        if(begin == 0 && distance == 0) return 0;
        //如果 i 为 1 ,而且第一个为 — 或者 +,说明字符串里面只有 正 或者 负 符号<细节>
        if (i == 1 && (sBuilder.charAt(0) == '-' || sBuilder.charAt(0) == '+')) return 0;
        if (i > 0) {
            //如果begin的长度大于10,肯定大于max 或者 min<细节>,不然长度太大,连long都放不下了
            if (d == 1 && begin > 10) return Integer.MIN_VALUE;
            if (d == 0 && begin > 10) return Integer.MAX_VALUE;
            //截取长度
            long myAtoi = Long.parseLong(sBuilder.substring(distance - begin + 1, distance + 1));
            //判断正负
            if (d == 1) myAtoi = -myAtoi;
            //满足题意,判断范围
            if (myAtoi <= Integer.MAX_VALUE && myAtoi >= Integer.MIN_VALUE) {
                return (int) myAtoi;
            } else if (myAtoi <= Integer.MIN_VALUE) {
                return Integer.MIN_VALUE;
            } else {
                return Integer.MAX_VALUE;
            }
        }
        //这个没办法,写着满足语法
        return 0;
    }
}

献丑了,呜呜呜~~~

接下来是我学习到的大佬的代码

class Solution {
    public int myAtoi(String str) {
        str = str.trim();
        if (str.length() == 0) return 0;
        if (!Character.isDigit(str.charAt(0))//判断下标为 零 是否为数字 + / -,是就跳出if语句
                && str.charAt(0) != '-' && str.charAt(0) != '+')
            return 0;
        long ans = 0L;//这样才好与边界值比较
        boolean neg = str.charAt(0) == '-';//等于,为true
        int i = !Character.isDigit(str.charAt(0)) ? 1 : 0;//判断从哪个下标开始 记数,是数字,从零下标计数
        while (i < str.length() && Character.isDigit(str.charAt(i))) {//判断是否为数字,并且防止数组越界
            ans = ans * 10 + (str.charAt(i++) - '0');//ans存的是正数
            if (!neg && ans > Integer.MAX_VALUE) {//正数越界情况 eg:-123
                ans = Integer.MAX_VALUE;
                break;
            }
            if (neg && ans > 1L + Integer.MAX_VALUE) {//负数越界情况,所以要加一
                ans = 1L + Integer.MAX_VALUE;
                break;
            }
        }
        return neg ? (int) -ans : (int) ans;//负数返回负数,正数返回负数
    }
}

 

Character.isDigit(str.charAt(i)); 这个东东就很巧妙,用于判断数字,就不用 0<= x <= 9

boolean neg = str.charAt(0) == '-'; 这个写法就很巧妙,的返回true or false

int i = !Character.isDigit(str.charAt(0)) ? 1 : 0; 这个也很巧妙,判断从什么地方开始

while (i < str.length() && Character.isDigit(str.charAt(i))) 虽然这里用了,charAt(i) 方法,但是前面限制了长度条件,防止空指针报错,数组越界,就很巧妙

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值