一天一大 lee(移除盒子)难度:困难-Day20200815
时间:2022-07-25
本文章向大家介绍一天一大 lee(移除盒子)难度:困难-Day20200815,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:[1]
给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k*k 个积分。当你将所有盒子都去掉之后,求你能获得的最大积分和。
示例
输入:boxes = [1,3,2,2,2,3,4,3,1]
输出:23
解释:
[1, 3, 2, 2, 2, 3, 4, 3, 1]
----> [1, 3, 3, 4, 3, 1] (3*3=9 分)
----> [1, 3, 3, 3, 1] (1*1=1 分)
----> [1, 1] (3*3=9 分)
----> [] (2*2=4 分)
提示
- 1 <= boxes.length <= 100
- 1 <= boxes[i] <= 100
抛砖引玉
抛砖引玉
思路
题目的逻辑为:每次移除连续相同字符,求每次移除个数的最大平方和
逻辑复杂的点为移除字符后字符连续情况可能发生变化
移除的思路:指定一点查询与其相同的元素,遇到与其不同的元素时:
- 在移除这个指定元素时先优先移除遇到的不同元素,使指定元素连续
- 切换指定元素,开始查询新的指定元素的连续个数
每次移除元素均取两种移除方式得到的最大值
- 动态规划使用 dp(i,j,k):
- i,j 是区间索引
- k 组件内最后一个元素(boxes[j])连续出现的次数
- dp(i,j,k)表示区间 i 到 j 的结果
- i->j 区间,可以指定移除边界元素(boxes[i]或 boxes[j])
- 使用方法 1 移除时,dp(i,j,k)由区间外指定元素个数的平方(k+1)*(k+1) + 新区间的值 dp(i,j-X,0) (X 为 i-j 区间移除连续指定元素形成的区间)
- 使用方法 2 移除时,已知指定元素已经存在 k 个,遍历区间遇到等于指定元素的则从该位置分割子区间,优先移除隔离连续指定元素的区间 A,使连续 k 与存在相同元素的区间连接 B A = (i, x, k + 1) B = (x + 1, j - 1, 0)
实现
- 声明 dp 三维数组:dp[i][j][k]
- 从最大的区间即:0->len-1,开始计算
- 计算连续(选择一个方向:从先向后或者从后向前)
- 指定区间的结果 = 被移除连续个数评分+移除后剩余区间的结果:dp[i][j][k] = getNum(boxes, dp, i, j - 1, 0) + (k + 1) * (k + 1)
- 枚举子区间:i->x->j(使用索引 x 截取子区间) 在 boxes[x]===boxes[j]时:就形成了一个风格区间点 i->j 至少包含一个元素等于 boxes[j],当该区间包含多个元素等于 boxes[j]时,为了避免重复计算值直接 dp 中取出
特殊情况
/**
* @param {number[]} boxes
* @return {number}
*/
var removeBoxes = function (boxes) {
let len = boxes.length,
dp = Array()
for (let i = 0; i < len; i++) {
dp[i] = new Array(len)
for (let j = 0; j < len; j++) {
dp[i][j] = new Array(len).fill(0)
}
}
function getNum(boxes, dp, i, j, k) {
if (i > j) return 0
// 区间计算过则直接返回
if (dp[i][j][k] != 0) return dp[i][j][k]
// 统计区间内连续子元素数量
while (i > j && boxes[j] === boxes[j - 1]) {
j--
k++
}
// 递归得到指定区间l->j的结果
dp[i][j][k] = getNum(boxes, dp, i, j - 1, 0) + (k + 1) * (k + 1)
// 在区间内枚举可能的存在的子区间
for (let x = i; x < j; x++) {
if (boxes[x] === boxes[j]) {
// dp[i][j][k]保存不同移除顺序下的最大值
dp[i][j][k] = Math.max(
dp[i][j][k],
getNum(boxes, dp, i, x, k + 1) + getNum(boxes, dp, x + 1, j - 1, 0)
)
}
}
return dp[i][j][k]
}
return getNum(boxes, dp, 0, len - 1, 0)
}
参考资料
[1]
题目:: https://leetcode-cn.com/problems/remove-boxes/
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法