LeetCode 算法:马戏团人塔

214 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 25 天,点击查看活动详情

马戏团人塔

原题地址

有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上。出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一点。已知马戏团每个人的身高和体重,请编写代码计算叠罗汉最多能叠几个人。

示例:

输入:height = [65,70,56,75,60,68] weight = [100,150,90,190,95,110]
输出:6
解释:从上往下数,叠罗汉最多能叠 6 层:(56,90), (60,95), (65,100), (68,110), (70,150), (75,190)

提示:

  • height.length == weight.length <= 10000

思路分析

方法一

  1. 首先组装数据,将每个人的身高体重组成一个对象,将每个人的信息存储到一个数组 data 中;
  2. 将数组按照身高升序,若身高相同则体重降序的方式进行排序;
  3. 因为身高已经升序了,因此循环判断其体重即可,若 data[i].weight > data[j].weight,则 res第i项res[i]res[j] + 1 的最大值;
  4. 寻找出 res 中的最大值返回即可。

方法二

  1. 步骤1,2同方法一,得到排序后的数据;
  2. 使用动态规划来维护一个动态数组 res,利用二分查找找出元素所在位置,若为 data.length 则给 res 添加元素,若在 1data.length - 1 的区间内就替换元素,这样可以得到满足条件的 res 数组;
  3. 因为题目要求返回数量即可,因此返回 res.length 就可以了。

方法二

AC 代码

方法一

/**
 * @param {number[]} height
 * @param {number[]} weight
 * @return {number}
 */
var bestSeqAtIndex = function(height, weight) {
    const data = []
    const res = [1]
    height.forEach((height, index) => {
        data.push({ height: height, weight: weight[index] })
    })
    data.sort((a, b) => a.height - b.height || b.weight - a.weight)
    for (let i = 1; i < data.length; i++){
        res[i] = 1
        for (let j = 0; j < i; j++) {
            if(data[i].weight > data[j].weight) {
                res[i] = Math.max(res[i], res[j] + 1)
            }
        }
    }
    return Math.max(...res)
};

结果:

  • 执行结果: 通过
  • 执行用时:6008 ms, 在所有 JavaScript 提交中击败了9.80%的用户
  • 内存消耗:49.6 MB, 在所有 JavaScript 提交中击败了70.59%的用户
  • 通过测试用例:43 / 43

方法二

/**
 * @param {number[]} height
 * @param {number[]} weight
 * @return {number}
 */
var bestSeqAtIndex = function(height, weight) {
    const data = []
    weight.forEach((w, i) => {
        data.push({ height: height[i], weight: w })
    })
    data.sort((a, b) => a.height - b.height || b.weight - a.weight)
    let res = [data[0]]
    data.forEach(item => {
        let left = 0, right = res.length - 1
        while(right >= left) {
            let mid = Math.floor((right - left) / 2 + left)
            res[mid].weight >= item.weight ? right = mid - 1 : left = mid + 1
        }
        res[left] = item
    })
    return res.length
};

结果:

  • 执行结果: 通过
  • 执行用时:144 ms, 在所有 JavaScript 提交中击败了84.31%的用户
  • 内存消耗:49.6 MB, 在所有 JavaScript 提交中击败了78.43%的用户
  • 通过测试用例:43 / 43

END