前提核心:
将全部数组分为两组,一组为取正数的(zheng),一组取负数的(fu);
可知:
zheng+fu=all
zheng-fu=target
那么zheng=(all+target)/2
如果all+target不能被2整除,就代表没办法使得zheng的数组和-fu的数组和为target,即返回0。
dp[i]表示正数数组和为i时有dp[i]种取法。
---------------------------------------------------------------------------------------------------------------------------------
※确定递推公式
只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法。
例如:dp[j],j 为5,
- 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
- 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
- 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
- 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
- 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包
那么凑整dp[5]也就是把 所有的 dp[j - nums[i]] 累加起来。
---------------------------------------------------------------------------------------------------------------------------------
思路分析:
- 首先,计算数组
nums
中所有元素的和,存储在all
变量中。 - 如果目标值
target
的绝对值大于数组元素和all
,则无法找到解,直接返回0。 - 如果目标值
target
与数组元素和all
之和为奇数,也无法找到解,直接返回0。 - 计算目标和的一半,存储在
zheng
变量中,这是要达到的目标。 - 创建一个大小为
zheng+1
的动态规划数组dp
,并初始化dp[0]
为1,表示和为0的组合有一种可能。 - 使用动态规划算法来计算达到目标和
zheng
的组合数。通过遍历数组nums
,在每次迭代中,更新dp
数组以记录达到各个和值的组合数。 - 最后,返回
dp[zheng]
,即达到目标和zheng
的组合数,这就是问题的解。
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int zheng, all = 0; // 定义变量zheng和all,分别用于存储目标值和数组中所有元素的和
int i, j;
// 计算数组中所有元素的和
for (i = 0; i < nums.size(); i++)
all += nums[i];
// 如果目标值的绝对值大于数组元素和,无法找到解,返回0
if (abs(target) > all)
return 0;
// 如果目标值与数组元素和之和为奇数,也无法找到解,返回0
if ((all + target) % 2 == 1)
return 0;
else
zheng = (all + target) / 2; // zheng表示目标和的一半,这是要达到的目标
// 创建一个大小为zheng+1的动态规划数组dp,初始化为0
vector<int> dp(zheng + 1, 0);
dp[0] = 1; // dp[0]初始化为1,表示和为0的组合有一种可能
// 使用动态规划来计算达到目标和zheng的组合数
for (i = 0; i < nums.size(); i++) {
for (j = zheng; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]]; // 更新dp数组,累加可能的组合数
}
}
return dp[zheng]; // 返回达到目标和zheng的组合数
}
};