您的位置:首页 > 文旅 > 美景 > 1049. 最后一块石头的重量 II

1049. 最后一块石头的重量 II

2025/7/1 16:06:27 来源:https://blog.csdn.net/m0_73939789/article/details/139596926  浏览:    关键词:1049. 最后一块石头的重量 II

Problem: 1049. 最后一块石头的重量 II

文章目录

  • 思路
  • 解题方法
  • 复杂度
  • Code

思路

为了得到最后一块石头的最小可能重量,我们可以将问题转为子集和的问题。找到一个子集,使得元素之和与剩余元素之后的差最小。也就是说,我们希望把石头分成两个集合,使得两个子集的重量差最小。由于我们可以通过将一个子集的重量从总重量中减去来得到另一个子集的重量,因此,我们的目标可以简化为寻找一个子集,其元素之和最接近总重量的一半。这样,两个子集之间的重量差就会是最小的。

解题方法

我们使用动态规划解决这个问题。定义一个一维数组 dp,其中 dp[j] 表示是否能够通过选择一些石头(不超过 j)达到总和 j。我们初始化 dp[0] 为 true,因为总和为 0 是总是可以实现的。
遍历数组 nums 中的每个元素 num,对于每一个 num,我们更新 dp 数组,使得 dp[j] 变为 dp[j-num]+num 和 dp[j] 中较大的值,只要 j >= num。
最后,dp 数组中的最大值就是我们要求的子集的近似最大重量。

复杂度

时间复杂度:

O ( n ⋅ m ) O(n⋅m) O(nm),其中 n 是数组 nums 的长度,m 是 nums 中所有元素的和除以 2 的结果。

空间复杂度:

O ( m ) O(m) O(m),其中 m 是 nums 中所有元素的和除以 2 的结果。这是因为我们需要一个大小为 m+1 的 dp 数组。

Code

class Solution {public int lastStoneWeightII(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}// 向下取整 01背包int near = near(nums, sum / 2);return sum - near - near;}public int near(int[] nums, int t) {int[] dp = new int[t + 1];for(int num : nums) {for(int j = t; j >= num; j--) {dp[j] = Math.max(dp[j], dp[j - num] + num);}}return dp[t];}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com