第 31 天

数学(困难)

剑指 Offer 14- II. 剪绳子 II

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1

示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

题解思路:取3

取3:通过求导可以发现,将原始长度分解成尽可能多的 3,则乘积最多

class Solution {
    public int cuttingRope(int n) {
        if(n == 2)
            return 1;
        if(n == 3)
            return 2;
        long res = 1;
        while(n > 4){
            res *= 3;
            res = res % 1000000007;
            n -= 3;
        }
        return (int)(res * n % 1000000007);
    }

}

剑指 Offer 43. 1~n 整数中 1 出现的次数

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

示例 1:

输入:n = 12
输出:5

示例 2:

输入:n = 13
输出:6

限制:

  • 1 <= n < 2^31

题解思路:规律

规律:(头疼)

class Solution {
    public int countDigitOne(int n) {
        //高位
        int high = n;
        //低位
        int low = 0;
        //当前位
        int cur = 0;
        int count = 0;
        int num = 1;
        while (high != 0 || cur != 0) {
            cur = high % 10;
            high /= 10;
            //这里我们可以提出 high * num 因为我们发现无论为几,都含有它 
            if (cur == 0) count += high * num;
            else if (cur == 1) count += high * num + 1 + low; 
            else count += (high + 1) * num;
            //低位
            low = cur * num + low;                  
            num *= 10;
        }
        return count;
    }
}

剑指 Offer 44. 数字序列中某一位的数字

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

请写一个函数,求任意第n位对应的数字。

示例 1:

输入:n = 3
输出:3

示例 2:

输入:n = 11
输出:0

限制:

  • 0 <= n < 2^31

题解思路:规律

规律:首先判断几位数,再

class Solution {
    public int findNthDigit(int n) {
        // digit :表示 digit 位数
        // max : 表示 dight 位数的最大下标
        // lastMax : 表示 dight - 1 位数的最大下标
        int max = 9, lastMax = 0;
        int digit = 1;
        // 找到这个数是几位数,也就是更新 digit 的过程
        while (n > max){
            digit++;
            lastMax = max;
            max += digit * 9 * Math.pow(10, digit - 1);
        }
        // 根据这个数的位数,就可以求出索引为n是哪个数的第几位
        int num = (n - lastMax)/digit + (int)Math.pow(10, digit - 1);
        int nth = (n - lastMax) % digit;
        // 特殊情况 余数为0时,更新 nth 为这个数的最后一位
        if(nth == 0){
            num--;
            nth = digit;
        }
        // 将求出的数 num 转化为 字符串,返回第 nth 位
        return String.valueOf(num).charAt(nth - 1) -'0';
    }
}