剑指 Offer 45. 把数组排成最小的数 剑指 Offer 66. 构建乘积数组 剑指 Offer 67. 把字符串转换成整数

剑指 Offer 45. 把数组排成最小的数

1、题目

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
在这里插入图片描述

2、题解

  此题求拼接起来的最小数字,本质上是一个排序问题。设数组 nums 中任意两数字的字符串为 x 和 y ,则规定 排序判断规则 为:

  • 若拼接字符串 x + y > y + x ,则 x “大于” y ;
  • 反之,若 x + y < y + x ,则 x “小于” y ;

x “小于” yy 代表:排序完成后,数组中 xx 应在 yy 左边;“大于” 则反之。

在这里插入图片描述

3、代码

解法一:内置函数

class Solution {
    public String minNumber(int[] nums) {
        String[] strs = new String[nums.length];
        for(int i = 0; i < nums.length; i++)
            strs[i] = String.valueOf(nums[i]);
        Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
        StringBuilder res = new StringBuilder();
        for(String s : strs)
            res.append(s);
        return res.toString();

    }
}

解法二:快排

剑指 Offer 66. 构建乘积数组

1、题目

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

在这里插入图片描述

2、题解

该题本质就是两个dp数组,分别维护 i 左侧、右侧的乘积和。

  • left数组: 循环记录每一行的乘积,都是在上一次 dp 数组的前提下,乘当前数字即可(i 左侧那一个) left[i] = left[i - 1] * a[i - 1];
  • right数组: 循环记录每一行的乘积,都是在上一次 dp数组的前提下,乘当前数字即可(i 右侧那一个) right[j] = right[j + 1] * a[j + 1];
  • 计算结果res: 将左右记录的 dp数组乘积乘起来

3、代码

class Solution {
    public int[] constructArr(int[] a) {
        int len = a.length;
        if(len == 0) return a;
        int[] left = new int[len];
        int[] right = new int[len];
        left[0] = right[len - 1] = 1;//初始化数组

        int[] res = new int[len];

        //维护 i 左侧乘积和
        for(int i = 1;i < len;i++){
            left[i] = left[i - 1] * a[i - 1];
        }
        //维护 i 右侧乘积和
        for(int j = len - 2;j >= 0;j--){
            right[j] = right[j + 1] * a[j + 1];
        }

        for(int i = 0;i < len;i++){
            res[i] = left[i] * right[i];
        }
        return res;

    }
}

剑指 Offer 67. 把字符串转换成整数

1、题目

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

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

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

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

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

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

说明:

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

在这里插入图片描述

2、题解

该题直接看代码注释吧,各种边界判断太繁琐了。

3、代码

class Solution {
    public int strToInt(String str) {
        //去除字符前后空格
        char[] chars = str.trim().toCharArray();
        if(chars.length == 0) return 0;
        //记录第一个字符是否是 “-” 
        int firstChar = 1;
        int i = 1;
        //如果首个非空格字符为负号,那么从位置1开始遍历字符串,并且结果需要变成负数
        if(chars[0] == '-'){
            firstChar = -1;
        }else if(chars[0] != '+'){//如果首个非空格字符不是负号也不是加号,那么从第一个元素开始遍历
            i = 0;
        }
        //结果
        int res = 0;
        //用于检查是否越界
        int number = Integer.MAX_VALUE / 10;

        for (int j = i; j < chars.length; j++) {
            //遇到非数字直接退出
            if(chars[j] > '9' || chars[j] < '0') break;
                            /*
                    这里这个条件的意思为,因为题目要求不能超过int范围,所以需要判断结果是否越界
                    因为res每次都会 * 10 ,所以外面定义了一个int最大值除以10的数字
                    此时只需要保证本次循环的res * 10 + chars[j] 不超过 int 即可保证不越界
                    res > number 意思是,此时res已经大于number了,他 * 10 一定越界
                    res == number && chars[j] > '7' 的意思是,当res == number时,即:214748364
                    此时res * 10 变成 2147483640 此时没越界,但是还需要 + chars[j],
                    而int最大值为 2147483647,所以当chars[j] > 7 时会越界
                 */
            if(res > number || (res == number && chars[j] > '7')){
                return firstChar == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }

            //字符获取数字需要 - '0' 的位移
            res = res * 10 + (chars[j] - '0');


        }
        //返回结果,需要判断正负
        return res * firstChar;
    }
}

参考:K神

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值