整数反转:通过模拟链表pop和push的概念实现反转

172 阅读4分钟

思路

  • "我的代码中"

    • 思路:

      • 将给定输入的数字转化成字符串,再转化成数组(split方法),再将数组反转(sort方法),再转化成数组(join方法),再转化成字符串,再转化成数字。
    • 缺点:

      • 没有考虑数字边界([−2^31, 2^31 − 1])。数组的最大长度是由 Number.MAX_SAFE_INTEGER 决定的,这是 JavaScript 能准确表示的最大整数,所以我们需要对给定输入的数字考虑数字边界。
      • 如果给定属于接近于边界,那么数组的长度就会非常长,非常影响性能。然而,实际上由于内存分配的原因,数组的长度可能会受到更小的限制。例如,在某些实现中,尝试创建一个长度接近或超过 2^32(约 4294967296)的数组可能会失败,因为这超出了某些内部机制处理的范围。
      • 需要对正数,负数,0分开考虑,有太多的if 判断了。
  • "官方解法中"

    • 思路:

      • 抽象意义上,可以分别维护两个新旧链表,在循环中,不断的将旧链表的最后一个值不断的pop,并不断往新链表中追加push,直到旧链表为空为止,这样就达到了反转的目标。
      • 实际意义上,我们需要模拟上面描述到的类似于新旧链表不断pop和push的概念,因为我们不可能真的去建立这么长的链表(数字边界:[−2^31, 2^31 − 1])。根据题目要求,输入一个数字,返回一个反转后的数字,于是我们可以扩展一下思路,看看有没有数学的方法可以达到类似的效果。答案是有的,在数学中可以采用%10和/10来模拟这种pop和push数字中的某一位的效果,例如对于 a === 123, (digit = a % 10) === 3,相当于把 3 给 pop 出来了,b 初始化为 0, 然后令 b = b * 10 + digit ,不就相当于将123的3 pop出来然后push进b的感觉吗,然后以此类推,2 pop ,2 push b, 这时候 b == 32,以此类推…
    • 优点

      • 考虑到了数字边界。

      • 不需要通过对正数负数0单独使用if去判断了

      • 如果输入为0,就不需要走循环,直接返回0了

      • 对于正负数,其实 % 和 / 操作正负数并没有什么异同,因此一套代码都可以适用于正负数,但是需要注意,对于 / 我们需要得到做完除法后的整数数字位,所以我们需要取整,正负数取整需要注意一下如下问题,对于负数,我们期望得到的是-5而不是-6,所以我们还需要对正负数做判断,为了尽量写太多的if,我们可以不使用Math.floor来取整,可以使用~~来取整,使用 ~~来操作数值,不论是正数还是负数,得到的都是原本的整数位,例如 ~~5.05 === 5, -5.03 === -5,这样不就达到我们的要求哩。

      • 解释一下~操作符: ~ 运算符返回一个数字或BigInt:对于数字,该运算符返回32位整数(刚好我们的题目要求也是32位,一切都是那么的巧合~)。对于BigInts,运算符返回BigInt

      console.log(Math.floor(5.95)); // Expected output: 5
      
      console.log(Math.floor(-5.05)); // Expected output: -6
      
      console.log(~~(-10.09)); // -10 
      console.log(Math.floor(-10.09)); // -11
      
      

题目

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

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

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

示例 1:


JavaScript 输入:x = 123 输出:321

示例 2:


JavaScript 输入:x = -123 输出:-321

示例 3:


JavaScript 输入:x = 120 输出:21

示例 4:


JavaScript 输入:x = 0 输出:0

提示:

  • -2^31 <= x <= 2^31 - 1

代码1:我的代码(已通过)


JavaScript /**

-   @param {number} x

-   @return {number} */ 
var reverse = function(x) {
    function reverseNum(num){ 
        
        return num.toString().split("").reverse().join("") * 1 }

        if(x === 0) return 0;
        if(x < 0) { 
            return -1 * reverseNum(-1 * x)
    } 
    return reverseNum(x) };

代码2:官方解法


JavaScript /**

-   @param {number} x

-   @return {number} */
    
  var reverse = function(x) { 

    let reverseNum = 0; while(x !== 0 ) {
    const digit = x % 10; x = ~~(x / 10); 
    reverseNum = reverseNum * 10 + digit; 
    
    if(reverseNum < Math.pow(-2,31) || reverseNum > Math.pow(2,31) -1) {
    
        return 0; // 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 } }

    return reverseNum; };