Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions src/1043.分隔数组以得到最大和.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* @lc app=leetcode.cn id=1043 lang=typescript
*
* [1043] 分隔数组以得到最大和
*
* https://leetcode.cn/problems/partition-array-for-maximum-sum/description/
*
* algorithms
* Medium (75.56%)
* Likes: 327
* Dislikes: 0
* Total Accepted: 40.1K
* Total Submissions: 53.1K
* Testcase Example: '[1,15,7,9,2,5,10]\n3'
*
* 给你一个整数数组 arr,请你将该数组分隔为长度 最多 为 k 的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。
*
* 返回将数组分隔变换后能够得到的元素最大和。本题所用到的测试用例会确保答案是一个 32 位整数。
*
*
*
* 示例 1:
*
*
* 输入:arr = [1,15,7,9,2,5,10], k = 3
* 输出:84
* 解释:数组变为 [15,15,15,9,10,10,10]
*
* 示例 2:
*
*
* 输入:arr = [1,4,1,5,7,3,6,1,9,9,3], k = 4
* 输出:83
*
*
* 示例 3:
*
*
* 输入:arr = [1], k = 1
* 输出:1
*
*
*
*
* 提示:
*
*
* 1 <= arr.length <= 500
* 0 <= arr[i] <= 10^9
* 1 <= k <= arr.length
*
*
*/

// @lc code=start
function maxSumAfterPartitioning(arr: number[], k: number): number {
const dp: number[] = Array(arr.length).fill(0);
dp[0] = arr[0];

let cur = arr[0];
for (let i = 1; i < arr.length; i++) {
if (i < k) {
cur = Math.max(cur, arr[i]);
dp[i] = cur * (i + 1);
} else {
cur = arr[i];
for (let j = 1; j <= k; j++) {
dp[i] = Math.max(dp[i], dp[i - j] + cur * j);
cur = Math.max(cur, arr[i - j]);
}
}
}

return dp[arr.length - 1];
}
// @lc code=end

(() => {
LCT.func(maxSumAfterPartitioning).auto();
})();
88 changes: 88 additions & 0 deletions src/1046.最后一块石头的重量.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* @lc app=leetcode.cn id=1046 lang=typescript
*
* [1046] 最后一块石头的重量
*
* https://leetcode.cn/problems/last-stone-weight/description/
*
* algorithms
* Easy (65.62%)
* Likes: 350
* Dislikes: 0
* Total Accepted: 129.1K
* Total Submissions: 196.5K
* Testcase Example: '[2,7,4,1,8,1]'
*
* 有一堆石头,每块石头的重量都是正整数。
*
* 每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x 。那么粉碎的可能结果如下:
*
*
* 如果 x == y,那么两块石头都会被完全粉碎;
* 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
*
*
* 最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。
*
*
*
* 示例:
*
*
* 输入:[2,7,4,1,8,1]
* 输出:1
* 解释:
* 先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1],
* 再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1],
* 接着是 2 和 1,得到 1,所以数组转换为 [1,1,1],
* 最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。
*
*
*
* 提示:
*
*
* 1
* 1
*
*
*/

// @lc code=start
function lastStoneWeight(stones: number[]): number {
stones.sort((a, b) => a - b);

while (stones.length > 1) {
const x = stones.pop();
const y = stones.pop();

const temp = Math.abs(x - y);
if (temp === 0) continue;

const len = stones.length;
if (len === 0) {
stones.push(temp);
break;
}

if (temp >= stones[len - 1]) {
stones.push(temp);
continue;
}
for (let i = 0; i < len; i++) {
if (temp < stones[i]) {
stones.splice(i, 0, temp);
break;
}
}
}

return stones.length ? stones[0] : 0;
}
// @lc code=end

// @lc code=end

(() => {
LCT.func(lastStoneWeight).auto();
})();
105 changes: 105 additions & 0 deletions src/1049.最后一块石头的重量-ii.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* @lc app=leetcode.cn id=1049 lang=typescript
*
* [1049] 最后一块石头的重量 II
*
* https://leetcode.cn/problems/last-stone-weight-ii/description/
*
* algorithms
* Medium (71.97%)
* Likes: 1059
* Dislikes: 0
* Total Accepted: 270K
* Total Submissions: 375.4K
* Testcase Example: '[2,7,4,1,8,1]'
*
* 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。
*
* 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
*
*
* 如果 x == y,那么两块石头都会被完全粉碎;
* 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
*
*
* 最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。
*
*
*
* 示例 1:
*
*
* 输入:stones = [2,7,4,1,8,1]
* 输出:1
* 解释:
* 组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
* 组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
* 组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
* 组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。
*
*
* 示例 2:
*
*
* 输入:stones = [31,26,33,21,40]
* 输出:5
*
*
*
*
* 提示:
*
*
* 1 <= stones.length <= 30
* 1 <= stones[i] <= 100
*
*
*/

// @lc code=start
function lastStoneWeightII(stones: number[]): number {
// 本质上是目标和,01背包问题,选出部分和接近但不超过 sum/2 的部分 A,这样可以保证两者差B-A最小
const sum = stones.reduce((a, b) => a + b, 0);
const target = Math.floor(sum / 2);

// dp[i] 为是否可以选出总和容量为 i 的选择
const dp = Array(target + 1).fill(false);
dp[0] = true;

// 01背包问题,先遍历选择,内部再倒序遍历背包容量
for (const weight of stones) {
for (let j = target; j >= weight; j--) {
// 如果容量为 j 时选当前石头,则 j - weight 容量也需要可以被其他石头组成
dp[j] = dp[j] || dp[j - weight];
}
}

// 设选出的选出的容量为 A,则另一部分 B = sum - A
// 则两者差为 B - A = sum - A - A = sum - 2*A
// 那么最小差即为最接近 sum/2 的,且 dp[i] = true 的组合
let k = target;
while (k >= 0) {
if (dp[k]) {
return sum - 2 * k;
}
k--;
}

// 上述一定可以出结果的(因为k=0时 dp[0] = true),下面这行其实永远不会走到
return -1;
}
// @lc code=end

(() => {
LCT.func(lastStoneWeightII).auto();
LCT.func(lastStoneWeightII).cases([
{
input: [[2, 7, 4, 1, 8, 1]],
output: 1
},
{
input: [[31, 26, 33, 21, 40]],
output: 5
}
]);
})();
Loading
Loading