1. 题目链接:494. 目标和
2. 题目描述:
给你一个非负整数数组
nums
和一个整数target
。向数组中的每个整数前添加
'+'
或'-'
,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1]
,可以在2
之前添加'+'
,在1
之前添加'-'
,然后串联起来得到表达式"+2-1"
。返回可以通过上述方法构造的、运算结果等于
target
的不同 表达式 的数目。示例 1:
输入:nums = [1,1,1,1,1], target = 3 输出:5 解释:一共有 5 种方法让最终目标和为 3 。 -1 + 1 + 1 + 1 + 1 = 3 +1 - 1 + 1 + 1 + 1 = 3 +1 + 1 - 1 + 1 + 1 = 3 +1 + 1 + 1 - 1 + 1 = 3 +1 + 1 + 1 + 1 - 1 = 3
示例 2:
输入:nums = [1], target = 1 输出:1
提示:
1 <= nums.length <= 20
0 <= nums[i] <= 1000
0 <= sum(nums[i]) <= 1000
-1000 <= target <= 1000
3. 解法(回溯):
3.1 算法思路:
对于每个数,可以选择加上或减去它,依次枚举每一个数字,在每个数都被选择时检查得到的和是否等于目标值。如果等于,则记录结果。
需要注意的是,为了优化时间复杂度,可以提前计算出数组中所有数字的和,以及数组的长度。这样可以快速判断当前的和减去剩余的数是否已经超过了目标值target
,或者当前的和加上剩下的数的和是否小于目标值target
,如果满足条件,则可以直接回溯
3.2 递归流程:
-
递归结束条件:
pos
与数组长度相等,判断当前状态的path
是否与目标值相等,若是计数加一 -
选择当前元素进行加操作,递归下一个位置,并更新参数
path
-
选择当前元素进行减操作,递归下一个位置,并更新参数
path
3.3 C++算法代码:
class Solution {
int ret, aim; // ret用于记录满足条件的路径数量,aim用于存储目标和
public:
int findTargetSumWays(vector<int>& nums, int target) {
aim = target; // 初始化目标和
dfs(nums, 0, 0); // 从数组的第一个元素开始搜索
return ret; // 返回满足条件的路径数量
}
void dfs(vector<int>& nums, int pos, int path) {
if (pos == nums.size()) { // 如果已经遍历完数组
if (path == aim) ret++; // 如果当前路径的和等于目标和,则增加满足条件的路径数量
return; // 结束当前递归
}
dfs(nums, pos + 1, path + nums[pos]); // 选择当前元素,将其加入路径中,继续搜索下一个元素
dfs(nums, pos + 1, path - nums[pos]); // 不选择当前元素,将当前元素从路径中移除,继续搜索下一个元素
}
};