LeetCode:整数反转(判断一个数是否超过Integer32位数的有效范围小技巧)

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-integer
获取整数的反转,这一步相对简单,获取x这个数的最后一个数字n,然后进行sum = sum * 10 + n这一步代码,然后不断进行循环,从而得到x数字的反转。
这里最大的问题是如何判断反转后整数是否超过了32位有效数字的范围。通过官方题解,我们明白只要Integer.MIN_VALUE <= sum <= Integer.MAX_VALUE这个范围,那么sum就还没有超过32位有符号整数的范围,为什么是这样咧?
我们由上面整数反转中可以知道sum = sum * 10 + n,那么我们是否可以将Integer.MAX_VALUE也化成这样的形式咧?答案是当然可以了, Integer.MAX_VALUE = (Integer.MAX_VALUE / 10 ) * 10 + 7,所以这时候我们只要保证sum * 10 + n <= (Integer.MAX_VALUE / 10) * 10 + 7成立,那么就可以保证不会超过32位有效数字的范围了
通过化简,我们可以知道(sum - Integer.MAX_VALUE / 10) * 10 <= 7 - n即可,这时候,我们能分成3中情况.
①sum > Integer.MAX_VALUE/10,那么不等式必然不会成立
②sum = Integer.MAX_VALUE/10,那么不等式必然成立
③sum < Integer.MAX_VALUE/10,那么不等式必然成立
所以,我们可以得出结论,当sum <= Integer.MAX_VALUE / 10的时候,那么进行相加的时候整数必然不会超过32位有符号整数的范围.最小值也是这样分析的。
对应代码:

class Solution {
    public int reverse(int x) {
         int sum = 0,n;
         boolean flag = x < 0 ? true : false;//flag表示x是否大于等于0
         if(flag){
             /*
             如果x小于0,那么flag为true,这时候x取相反数,即x = -x,注意
             不可以是x -= x,否则最后得到的就不是想要的结果,而是这一步之
             后x变成0
             */
             x = -x;
         }
          while(x != 0){
            n = x % 10;
            if(sum < Integer.MIN_VALUE / 10 || sum > Integer.MAX_VALUE / 10)// Integer.MIN_VALUE / 10 <= sum <= Integer.MAX_VALUE / 10时,sum没有超过32位有符号数字的范围
                return 0;
            sum = sum * 10 + n;
            x /= 10;
         }
         if(flag) //如果x是负数,那么最后反转的数字也应该是一个负数,所以需要将sum变成他的相反数
            sum = -sum;
         return sum;
    }
}

在这里插入图片描述

LeetCode: 字符串换成整数
写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231)

示例 1:

输入: “42”
输出: 42
示例 2:

输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:

输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。
示例 4:

输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:

输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof

思路:
1、首先我们需要明白,一个字符串转成一个整数,并且题目已经明确要求了不可以使用库函数进行转换,所以将一个字符串转成一个整数的时候,我们首先调用toCharArray,将字符串转成一个字符数组。然后遍历这个字符数组,执行reult = result * 10 + arr[i] - '0’从而获取字符串对应的数字.但是有可能最后result * 10之后会发生越界。所以需要在进行这一步之前将result和Integer.MAX_VLUE / 10进行比较。

  • result > Integer.MAX_VALUE / 10,那么进行下一步的时候就会发生越界。所以这时候需要判断第一个字符是否是一个负号,从而判断最后直接返回的是Integer.MAX_VALUE,还是Integer.MIN_VALUE
  • result == Integer.MAX_VALUE / 10的时候还不可以判断最后的结果result会发生越界的问题,比如2147483646,-2147483647,虽然result = Integer.MAX_VALUE / 10 = 214748364,但是最后一个数并没有超过6,所以就不算是越界。所以在result == Integer.MAX_VALUE的时候,我们还需要判断最后一个数字是否会大于‘7’或者大于等于‘8’,如果等于7,并且开头符号是一个整数,那么就这时候刚好等于Integer.MIN_VALUE,将其返回即可,大于8的话,那么就发生了越界。否则,如果开头的是一个正号,并且最后一个数字大于等于8,比且resul t== Integer.Max_vALUE / 10
    2、如果输入的字符串是空的,或者是一个空格串,那么直接返回0,表示没有办法进行合法的交换。
class Solution {
    public int strToInt(String str) {
          if(str == null)//如果字符串是空的,或者
             return 0;
          str = str.trim();//去除首尾的空格字符
          if(str.length() == 0)
             return 0;//一开始字符串是一个空串或者空格串,所以长度>= 0,去除空格之后还需判断它的长度是否为0,如果为0,直接返回0
          char[] ch = str.toCharArray();//将字符串转成字符数组
          if(ch[0] == '-' || ch[0] == '+' || isDigit(ch[0])){
                 //如果第一个字符是正负号,或者是一个数字字符,那么就开始进行拼接
                int result = 0,i;
                if(isDigit(ch[0])){
                    //如果第一个字符是一个正数
                    result = ch[0] - '0';
                }
                for(i = 1; i < ch.length; i++){
                    if(!isDigit(ch[i]))
                       break;//如果是一个非数字字符,那么退出转换
                    if(result >= Integer.MAX_VALUE / 10){
                        //如果这个数字大于了int的最大值,那么直接返回int的最大值
                        if(result > Integer.MAX_VALUE / 10){
                            if(ch[0] == '-')
                               return Integer.MIN_VALUE;
                            return Integer.MAX_VALUE;
                        }
                        //当前的result == Integer.MAX_VALUE / 10的时候,还需要考虑最后一个数字是否为7或者为8,或者其他
                        if(ch[0] == '-' &&  ch[i] >= '8')
                            return Integer.MIN_VALUE;
                        else if(ch[0] != '-' && ch[i] >= '7')
                            return Integer.MAX_VALUE;
                        
                    }
                    result = result * 10 + ch[i] - '0';
                   // System.out.println("result = " + result + ", Integer.MAX_VALUE = " + Integer.MAX_VALUE);
                    
                }
                if(ch[0] == '-')
                    result = -result;
                return result;

          }
          return 0;//如果第一个字符是一个非法字符,那么直接返回0
    }
    public boolean isDigit(char ch){
        return ch >= '0' && ch <= '9';
    }
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值