【LeetCode】字符串转换整数 (atoi) [M](模拟)

这篇具有很好参考价值的文章主要介绍了【LeetCode】字符串转换整数 (atoi) [M](模拟)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

8. 字符串转换整数 (atoi) - 力扣(LeetCode)

一、题目

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

  1. 读入字符串并丢弃无用的前导空格
  2. 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
  3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  4. 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
  5. 如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
  6. 返回整数作为最终结果。

注意:

  • 本题中的空白字符只包括空格字符 ' ' 。
  • 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1:

输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"42"(读入 "42")
           ^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。

示例 2:

输入:s = "   -42"
输出:-42
解释:
第 1 步:"   -42"(读入前导空格,但忽视掉)
            ^
第 2 步:"   -42"(读入 '-' 字符,所以结果应该是负数)
             ^
第 3 步:"   -42"(读入 "42")
               ^
解析得到整数 -42 。
由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42 。

示例 3:

输入:s = "4193 with words"
输出:4193
解释:
第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
         ^
第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
         ^
第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
             ^
解析得到整数 4193 。
由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193 。

提示:

  • 0 <= s.length <= 200
  • s 由英文字母(大写和小写)、数字(0-9)、' ''+''-' 和 '.' 组成

二、代码

class Solution {
    public int myAtoi(String str) {
        // 字符串转换为字符数组
        char[] s = str.toCharArray();
        // 字符串长度
        int n = s.length;
        // 标记是否已经完成了去除前缀空格的流程
        boolean flag1 = false;
        // 标记是否已经完成了读取符号位的流程
        boolean flag2 = false;
        // 记录符号位
        int signed = 1;
        // 记录答案
        // 这种字符串转数字类型的题,需要在过程中用负数统计,因为系统最小值绝对值比最大值大一个(负数的范围比正数的范围多1个),拿它做底更安全。
        // 比如转换字符串"-2147483648"为一个int数,用正数处理就不够了,只能用负数处理才行。
        // 如果不是负数的,也先将其转化为负数,处理完了之后再转回正数。
        int ans = 0;

        // 下面就是计算两个不能越界的范围,因为在统计过程中我们使用的是负数,所以这里就用负数的最小值来判断溢出边界
        int minq = Integer.MIN_VALUE / 10;
        int minr = Integer.MIN_VALUE % 10;

        // 开始遍历字符串
        for (int i = 0; i < n; i++) {
            // 如果去除前缀空格的流程,并且当前的字符仍然是空格,则跳过该字符继续下一个
            if (!flag1 && s[i] == ' ') {
            } else {
                // 当第一次找到了一个不是空格的字符时,说明第一个阶段已经结束了,将flag设置为true
                flag1 = true;
                // 第一次进入到该分支,flag2一定是false,我们要先去判断第一个非空格的字符是否是符号位
                if (!flag2) {
                    // 先将flag2设置为true,因为该流程只会执行一次
                    flag2 = true;
                    // 如果符号位是负,则将signed设置为-1
                    if (s[i] == '-') {
                        signed = -1;
                        // 该位置是非数字,直接跳过
                        continue;
                    } else if (s[i] == '+') {
                        // 如果有正号符号位,也需要跳过后续的流程
                        continue;
                    }
                }

                // 当完成了第一个流程和第二个流程后,后面就开始读取数字字符了,当第一次读取到非数字字符时,就结束直接跳出循环,后面的字符串就不管了
                if (s[i] >= '0' && s[i] <= '9') {
                    // 【这里有一个技巧点,上面说了我们要按照负数去做处理,这样更安全,所以这里要用'0' - s[i],当所有流程结束后我们再将符号位转回去即可】
                    int num = '0' - s[i];

                    // 【第二个技巧——防溢出】
                    // 因为我们使用负数来收集的,所以循环中的ans一定是一个负数
                    // 	1) ans结果是负数,如果比系统最小/10还小,那么在后面的乘10操作之后必溢出,这种情况就可以直接返回系统最大或系统最小值
                    //  2) 如果ans == 系统最小值,则乘10之后不会溢出,此时res*10=-2147483640,相当于系统最小值把最后一位变成0,也就是说只要是在个位上加一个小于-8的数(即小于系统最小值个位的那个数minr),就一定低于系统最小值,溢出了。在后面的操作中,ans要加num,所以如果num小于minr,则加上这部分必溢出。这种情况就可以直接返回系统最大或系统最小值
                    if (ans < minq || (ans == minq && num  < minr)) {
                        // 根据符号位来决定返回最大值还是最小值
                        return signed == -1 ? Integer.MIN_VALUE : Integer.MAX_VALUE;
                    }
                    // 收集数字
                    ans = ans * 10 + num;
                } else {
                    // 在收集数字的过程中第一次遍历到非数字字符时就结束循环
                    break;
                }
            }
        }

        // 如果此时ans此时正好是系统最小值,但是符号位是正数,我们知道最大值的绝对值比最小值的绝对值小1,所以此时答案应该是已经超过系统最大值了,算溢出了,直接返回系统最大
        if (signed == 1 && ans == Integer.MIN_VALUE) {
            return Integer.MAX_VALUE;
        }
        
        // 因为之前我们是按照负数来收集,执行到这里就说明最终的答案没有溢出(大于等于系统最小,小于等于系统最大),所以我们直接将ans取相反数,消除之前按负数收集的影响
        ans = -ans;
        // 返回答案  (符号位 * ans)
        return  (signed * ans);
    }
}

三、解题思路 

这道题不难,就是麻烦,就是需要考虑很多判断条件。并且这道题最关键的一个技巧就是判断大数是否溢出的技巧。

详细的讲解都在代码注释中文章来源地址https://www.toymoban.com/news/detail-470413.html

到了这里,关于【LeetCode】字符串转换整数 (atoi) [M](模拟)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 考研算法第46天: 字符串转换整数 【字符串,模拟】

    题目前置知识 c++中的string判空 c++中最大最小宏 字符串使用+发运算将字符加到字符串末尾  题目概况 AC代码

    2024年02月12日
    浏览(55)
  • 【LeetCode-中等】剑指 Offer 67. 把字符串转换成整数(详解)

    写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续

    2024年02月15日
    浏览(51)
  • (其他) 剑指 Offer 67. 把字符串转换成整数 ——【Leetcode每日一题】

    难度:中等 写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可

    2024年02月09日
    浏览(56)
  • 用C语言写一个函数,把字符串转换成整数

    这是一个很有意思的问题。请不要把这个问题想的太简单了,考虑问题时应该尽可能的全面一些。请先思考并且实现这个函数,再来看讲解。 分析一下:函数名是StrToInt,那么可以这么调用: 如果你写的程序能够正确输出1234,然后就觉得这道题就这样了,那么考虑的就不够

    2023年04月09日
    浏览(52)
  • C++中如何将string(字符串)转换为int(整数)

    C++ 编程语言有一些内置数据类型: int , 对于整数(例如 10、150) double ,对于浮点数(例如 5.0、4.5) char ,对于单个字符(例如“D”、“!”) string ,对于字符序列(例如“Hello”) bool , 对于布尔值(true 或 false) C++ 是一种 强类型 编程语言,这意味着当您创建变量时,你

    2024年02月06日
    浏览(76)
  • c++:string相关的oj题(把字符串转换成整数、344.反转字符串、387. 字符串中的第一个唯一字符、917. 仅仅反转字母)

    传送门 首先处理空字符串为空的情况() 再处理第一个字符可能为 + - 的情况,直接定一个 flag 初始化为1,遇到 - 就赋值为-1 接下来就利用迭代器进行循环,如果是字符数字就直接使用 ret = ret * 10 + (*it - \\\'0\\\'); 是其他字符,直接return 0;了 传送门 大家学习了c++,可能直接就想

    2024年01月23日
    浏览(77)
  • LeetCode 2788.按分隔符拆分字符串:模拟(字符串处理)

    力扣题目链接:https://leetcode.cn/problems/split-strings-by-separator/ 给你一个字符串数组 words 和一个字符 separator ,请你按 separator 拆分 words 中的每个字符串。 返回一个由拆分后的新字符串组成的字符串数组, 不包括空字符串 。 注意 separator 用于决定拆分发生的位置,但它不包含在

    2024年01月21日
    浏览(57)
  • 【洛谷 P2084】进制转换 题解(模拟+字符串)

    无 今天小明学会了进制转换,比如(10101)2 ,那么它的十进制表示的式子就是 : 1*2 4+0*2 3+1*2 2+0*2 1+1*2^0, 那么请你编程实现,将一个M进制的数N转换成十进制表示的式子。 注意:当系数为0时,该单项式要省略。 两个数,M和N,中间用空格隔开。 共一行,一个十进制表示的式

    2024年01月20日
    浏览(35)
  • LeetCode·每日一题·415. 字符串相加·模拟

    作者:小迅 链接:https://leetcode.cn/problems/add-strings/solutions/2347085/mo-ni-zhu-shi-chao-ji-xiang-xi-by-xun-ge-fges/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。   题意 - 给定二个字符串,计算它们的和并同样以字符串形式返回。 直接从

    2024年02月16日
    浏览(40)
  • LeetCode 2810. Faulty Keyboard【模拟,双端队列,字符串】简单

    本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,

    2024年02月13日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包