Leetcode刷题详解—— 目标和

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 递归流程:

  1. 递归结束条件:pos与数组长度相等,判断当前状态的path是否与目标值相等,若是计数加一

  2. 选择当前元素进行加操作,递归下一个位置,并更新参数path

  3. 选择当前元素进行减操作,递归下一个位置,并更新参数path

Leetcode刷题详解—— 目标和_第1张图片

3.3 C++算法代码:

class Solution {
    int ret, aim; // ret用于记录满足条件的路径数量,aim用于存储目标和
public:
    int findTargetSumWays(vector& nums, int target) {
        aim = target; // 初始化目标和
        dfs(nums, 0, 0); // 从数组的第一个元素开始搜索
        return ret; // 返回满足条件的路径数量
    }
    void dfs(vector& 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]); // 不选择当前元素,将当前元素从路径中移除,继续搜索下一个元素
    }
};

你可能感兴趣的:(leetcode,深度优先,算法)