01数字反转.7

01数字反转.7

https://leetcode-cn.com/problems/reverse-integer/

在这里插入图片描述

1.Comprehensive两种理解思路

理解1:理解为逆序输出

在这里插入图片描述

理解2:理解为首尾交换

在这里插入图片描述

2. Choose数据结构及算法思维选择

方案1:逆序输出(暴力解法)

  • 整数转字符串,字符串转数组
  • 数据结构:字符数组
  • 算法思维:遍历

方案2:首尾交换(优化解法)

  • 整数转字符串,字符串转数组
  • 数据结构:字符数组
  • 算法思维:遍历

数据结构-数组

  • 数组容量固定不变
  • 使用连续的物理空间存取数据
  • O(1)复杂度读取任意元素

3.Code基本解法及编码实现

解法1:暴力解法

  1. 整数转字符串,再转为字符数组
  2. 反向遍历字符数组,并将元素存到新数组中
  3. 将新数组转为字符串,再转为整数输出

在这里插入图片描述

解法1:暴力解法边界和细节问题

  • 边界问题:

    • 数组索引越界

    • 数值溢出边界:溢出则返回0

  • 细节问题:

    • 首位不为0

    • 符号位处理

我写的解法1:char数组逆序

class Solution {
    
    
    public int reverse(int x) {
    
    
        int signed = x > 0 ? 1 : -1;
        long number = x;//这里转为long,避免溢出,
        number = Math.abs(number);
        //1. 整数转字符串,字符串转字符数组
        String str = String.valueOf(number);
        char[] oldCharArray = str.toCharArray();
        char[] newReveredCharArray = new char[oldCharArray.length];
        //2. 逆序输出字符数组
        for (int i = oldCharArray.length - 1; i >= 0; i--) {
    
    
            newReveredCharArray[oldCharArray.length - 1 - i] = oldCharArray[i];
        }
        //3. 字符数组转字符串,再转为整数
        String reversedStr = String.valueOf(newReveredCharArray);
        long unsignedResult = Long.parseLong(reversedStr);
        long result = signed * unsignedResult;
        if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
    
    
            result = 0;
        }
        return (int) result;
    }
}

我写的解法2:StringBuffer的reverse API逆序

    /**
     * 使用StringBuffer的reverse API简化数组操作
     */
    class Solution {
    
    
        public int reverse(int x) {
    
    
            int signed = x > 0 ? 1 : -1;
            long number = x;//这里转为long,避免Integer.MIN_VALUE取反溢出
            number = Math.abs(number);
            //1. 整数转字符串,字符串转字符数组
            String str = String.valueOf(number);
            //3. 字符数组转字符串,再转为整数
            String reversedStr = new StringBuffer(str).reverse().toString();
            long unsignedResult = Long.parseLong(reversedStr);
            long result = signed * unsignedResult;
            if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
    
    
                result = 0;
            }
            return (int) result;
        }
    }

我写的解法3:另一种溢出判断

class Solution {
    
    
    public int reverse(int x) {
    
    
        int signed = x > 0 ? 1 : -1;
        long number = x;//这里转为long
        number = Math.abs(number);
        //1. 整数转字符串,字符串转字符数组
        String str = String.valueOf(number);
        //3. 字符数组转字符串,再转为整数
        String reversedStr = new StringBuffer(str).reverse().toString();
        long unsignedResult = Long.parseLong(reversedStr);
        long result = signed * unsignedResult;
        if (result != (int) (result)) {
    
    //如果
            result = 0;
        }
        return (int) result;
    }
}

拉勾网给的解法:char数组逆序

class Solution {
    
    
    /**
     * 编写代码时,先编写主体代码
     */
    public int reverse(int x) {
    
    
        if (x == Integer.MIN_VALUE) {
    
    
            // 整数类型最小值的绝对值 比 最大值的绝对值 大1
            return 0; // 反转必然溢出,返回0
        }
        int sign = x > 0 ? 1 : -1; // 符号
        x = x < 0 ? x * -1 : x; // 无论正负,都当成正数
        // 1.整数转字符串,再转字符数组
        String str = String.valueOf(x);
        char[] chars = str.toCharArray();
        // 2.反向遍历字符数组,并将元素存储到新数组中
        int len = chars.length;
        char[] array = new char[len];
        for (int i = 0; i < len; i++) {
    
     // 遍历新数组
            array[i] = chars[len - 1 - i];
        }
        // 3.将新数组转成字符串,再转成整数输出
        long value = Long.valueOf(String.valueOf(array));
        boolean b = value > Integer.MAX_VALUE || value < Integer.MIN_VALUE;
        int result = b ? 0 : (int) value; // 数值越界:溢出则返回0
        return result * sign; // 符号还原 }
    }
}

时间复杂度与空间复杂度分析

时间复杂度:O(n)

  • 将整数转成字符串O(n)
  • 遍历字符数组O(n)
  • O(n) +O(n)=O(2n)
  • 忽略常数后:O(n)

空间复杂度:O(n)

  • 一个字符串O(n)
  • 一个新数组O(n)
  • O(n) +O(n)=O(2n)
  • 忽略常数后:O(n)

解法2:首尾交换

  1. 整数转字符串,再转为字符数组
  2. 遍历字符数组,数组内元素原地首尾交换
  3. 将新数组转为字符串,再转为整数输出

解法2:首尾交换边界和细节问题

  • 边界问题
    • 数组索引越界
      • 数组为偶数,完成标志为start>end
      • 数组为奇数,完成标志为start=end
      • 所以边界条件为start<end
    • 数值溢出边界:溢出则返回0
  • 细节问题
    • 首尾不为0
    • 符号处理

我写的解法1:char数组首尾交换

class Solution {
    
    
    public int reverse(int x) {
    
    
        int signed = x > 0 ? 1 : -1;
        long number = x;//这里转为long
        number = Math.abs(number);
        //1. 整数转字符串,字符串转字符数组
        String str = String.valueOf(number);
        char[] charArray = str.toCharArray();
        //2. 逆序输出字符数组
        int startIndex = 0, endIndex = charArray.length - 1;
        while (startIndex < endIndex) {
    
    
            char temp = charArray[startIndex];
            charArray[startIndex] = charArray[endIndex];
            charArray[endIndex] = temp;
            startIndex++;
            endIndex--;
        }
        //3. 字符数组转字符串,再转为整数
        String reversedStr = String.valueOf(charArray);
        long unsignedResult = Long.parseLong(reversedStr);
        long result = signed * unsignedResult;
        if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
    
    
            result = 0;
        }
        return (int) result;
    }
}

拉钩网给的解法:char数组首尾原地交换

class Solution {
    
    
    /**
     * 编写代码时,先编写主体代码
     */
    public int reverse(int x) {
    
    
        if (x == Integer.MIN_VALUE) {
    
    
            // 整数类型最小值的绝对值 比 最大值的绝对值 大1
            return 0; // 反转必然溢出,返回0
        }
        int sign = x > 0 ? 1 : -1; // 符号
        x = x < 0 ? x * -1 : x; // 无论正负,都当成正数
        // 1.整数转字符串,再转字符数组
        String str = String.valueOf(x);
        char[] chars = str.toCharArray();
       int startIndex = 0, endIndex = chars.length - 1;
        while (startIndex < endIndex) {
    
    
            char temp = charArray[startIndex];
            chars[startIndex] = chars[endIndex];
            chars[endIndex] = temp;
            startIndex++;
            endIndex--;
        }
        // 3.将新数组转成字符串,再转成整数输出
        long value = Long.valueOf(String.valueOf(chars));
        boolean b = value > Integer.MAX_VALUE || value < Integer.MIN_VALUE;
        int result = b ? 0 : (int) value; // 数值越界:溢出则返回0
        return result * sign; // 符号还原 }
    }
}

时间复杂度与空间复杂度

时间复杂度:O(n)

  • 将整数转成字符串O(n)

  • 遍历字符数组O(n)

  • O(n) +O(n)=O(2n)

  • 忽略常数后:O(n)

空间复杂度:O(n)

  • 一个字符串O(n)
  • 一个新数组O(n)
  • 绝对空间消耗降低:O(n)

4.Consider思考更优解及编码实现

  1. 剔除无效代码或优化空间消耗
  • 操作是必须的吗?
  • 数据结构是必须的吗?
  1. 寻找更好的算法思维
    • 既然是整数,能否用数学思维?
    • 借鉴其它算法

解法:数学思维解法

在这里插入图片描述

数学思维解法边界和细节问题

  • 边界问题

    • 什么时候结束?

    • 从低位到高位处理,最高位结束

      1. 最高位/10==0
      2. 最高位%10==最高位
    • 数值溢出边界:溢出则返回0

      • 用long存放,溢出int则返回0
      • 新整数补充最后一位前判断溢出
  • 细节问题

    • 同上

5. Code 最优解思路及编码实现

我写的解法1:数学思维法

class Solution {
    
    
    public int reverse(int x) {
    
    
        if (x == Integer.MIN_VALUE) {
    
    
            //因为Integer.MIN_VALUE的绝对值必溢出,Integer.MAX_VALUE的绝对值不会溢出
            return 0;
        }
        int signed = x > 0 ? 1 : -1;
        long number = Math.abs(x);
        long digit;
        long unSignedResult = 0;
        while (number != 0) {
    
    
            digit = number % 10;
            unSignedResult = unSignedResult * 10 + digit;
            number = number / 10;
        }
        long result = unSignedResult * signed;
        if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
    
    
            result = 0;
        }
        return (int) result;
    }
}

时间复杂度与空间复杂度

时间复杂度:O(n)

• 遍历整数的每一位:O(n)

空间复杂度:O(1)

• 只需要一个整数变量O(1)

6.Change变形延伸

  • (练习)对长整形数据进行反转
  • (练习)对字符串进行反转

7.最优解通用解法

class Solution {
    
    
    public long reverse(long x) {
    
    
        long result = 0;
        while (x != 0) {
    
    
            if (result > Long.MAX_VALUE / 10 || result < Long.MIN_VALUE / 10) {
    
    
                return 0;
            }
            long digit = x % 10;
            x /= 10;
            result = result * 10 + digit;
        }
        return result;
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sinat_26394043/article/details/132678200