📌  相关文章
📜  将数组拆分为两个子数组,使其总和的差异最小(1)

📅  最后修改于: 2023-12-03 15:09:37.080000             🧑  作者: Mango

将数组拆分为两个子数组,使其总和的差异最小

当我们需要将一个数组拆分为两个子数组,使得它们的总和差异最小时,可以使用动态规划来解决。

思路

我们可以先计算出整个数组的总和,然后设定一个目标值,这个目标值是数组总和的一半,即 $target=\frac{sum}{2}$。

接下来,我们可以定义一个二维数组 $dp[i][j]$,表示前 $i$ 个数字中,是否可以选取若干个数字,使得它们的和恰好等于 $j$。可以得到以下两个状态转移方程:

$$ dp[i][j] = \begin{cases} dp[i-1][j] & \text{不选第$i$个数字}\ dp[i-1][j-nums[i]] & \text{选第$i$个数字} \end{cases} $$

然后我们只需要从 $dp[n][target]$ 开始,倒推出哪些数字被选中,哪些没有被选中即可。

代码
def splitArray(nums: List[int]) -> int:
    n = len(nums)
    s = sum(nums)
    target = s // 2
    dp = [[False] * (target + 1) for _ in range(n + 1)]
    dp[0][0] = True
    for i in range(1, n + 1):
        for j in range(target + 1):
            dp[i][j] = dp[i - 1][j]
            if j >= nums[i - 1]:
                dp[i][j] |= dp[i - 1][j - nums[i - 1]]
    for j in range(target, -1, -1):
        if dp[n][j]:
            return s - 2 * j
    return -1

该代码的返回值为两个数组的总和差值的绝对值的最小值。如果返回值为 $-1$,则表示不能将数组拆分为两个子数组使得它们总和的差值最小。