算法打卡第二十四天

138 阅读3分钟
  1. 剑指 Offer 14- I. 剪绳子
  2. 剑指 Offer 57 - II. 和为s的连续正数序列
  3. 剑指 Offer 62. 圆圈中最后剩下的数字

剑指 Offer 14- I. 剪绳子

给你一根长度为 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。

题意理解: 将n拆分成m段,返回每段的乘积的最大值 本人使用暴力枚举,找出的规律 特殊情况,特殊处理 小于3返回n-1, 可以看出拆3则全拆3; 如果余数为1则取一个4,其他为3; 如果余数为2, 则拆成一个2和其他3 m:3 2, 1 m:4 2, 2 m:5 3, 2 m:6 3, 3 m:7 3, 4 m:8 3, 3, 2 m:9 3, 3, 9 m:10 3, 3, 4 m:11 3, 3, 3, 2 m:12 3, 3, 3, 3

提示: 2 <= n <= 58

var cuttingRope = function(n) {
    if (n <= 3) return n - 1;
    let m = Math.floor(n / 3),
        num = n % 3;
    if (num === 0) return Math.pow(3, m);
    if (num === 1) return Math.pow(3, m - 1) * 4;
    return num * Math.pow(3, m)
};

剑指 Offer 57 - II. 和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

题意理解: 找出从1开始到target中,连续的数字之和为target的所有情况

  1. 声明变量currentNum表示当前数的和,arr表示返回的结果,list存储当前和小于target的值
  2. i=1,遍历target
  3. 如果currentNum===target,则list中的值就符合条件,是真确答案之一,将list前面以为出数组,当前数加入数组,并计算当前值,i累加
  4. 如果currentNum< target,则当前面数加入数组,并计算当前值,i累加
  5. 如果currentNum> target,则去掉前面的数字,并计算当前值

1 <= target <= 10^5

var findContinuousSequence = function(target) {
    let currentNum = 0;
    const arr = [];
    let list = [];
    let i = 1;
    while (i <= target) {
        if (currentNum === target) {
            arr.push([...list])
            list.push(i)
            const deleteNum = list.shift()
            currentNum += i;
            currentNum -= deleteNum;
            i++
        } else if (currentNum < target) {
            list.push(i)
            currentNum += i;
            i++
        } else {
            const deleteNum = list.shift()
            currentNum -= deleteNum;
        }
    }
    return arr;
};

剑指 Offer 62. 圆圈中最后剩下的数字

0, 1, ···, n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

题意理解: 0-n-1个数字将排成一个环,一次删除换种第m个数字,知道只剩下最后一个数字 找规律: f(n) = (f( n - 1 ) + m) % n 参考此处

以n = 5, m = 3为例 初始化 0 1 2 3 4 第一轮 0 1 3 4 去除2 第二轮 1 3 4 去除0 第三轮 1 3 去除4 第四轮 3 去除1

以n = 4, m = 3为例 初始化 0 1 2 3 第一轮 0 1 3 去除2 第二轮 0 3 去除1 第三轮 0 去除3

以n = 3, m = 3为例 初始化 0 1 2 第一轮 0 1 去除2 第二轮 1 去除1

示例 1: 输入: n = 5, m = 3 输出: 3

示例 2: 输入: n = 10, m = 17 输出: 2

限制: 1 <= n <= 10^5 1 <= m <= 10^6

动态规划 反序

var lastRemaining = function(n, m) {
    let x = 0;
    for (let i = 2; i <= n; i++) {
        x = (x + m) % i
    }
    return x
};

暴力

var lastRemaining = function(n, m) {
    let arr = [];
    for (let i = 0; i < n; i++) {
        arr[i] = i
    }
    let num = 0;
    let currentIndex = 0;
    while (arr.length > 1) {
        num++;
        if (num === m) {
            arr.splice(currentIndex, 1);
            currentIndex--;
            num = 0;
        }
        if (currentIndex >= arr.length - 1) {
            currentIndex = 0;
        } else {
            currentIndex++;
        }
    }
    return arr[0]
};