leetcode 494. 目标和

leetcode 494. 目标和

题目

给你一个非负整数数组 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

思路

一开始想着直接回溯的,就直接ac了,非常简单,在我的第一版代码里。但这个是在代码随想录01背包里的问题,所以要思考怎么转化为背包。实际上01背包很多题都是把数组拆成几组,这里就是两组一组a是用来做正数,另一组b做负数。那么两者a+b=sum,a-b=target,二式相加后可知就是找到把num数组中所有数之和为(sum+target)/2的方案,这里有两个坑,其中一个是sum+target要是偶数才行,另一个写在了代码注释里

代码

复制代码
// 第一版
class Solution {
    int res = 0;
    int sum = 0;
    public int findTargetSumWays(int[] nums, int target) {
        dfs(nums, 0, target);
        return res;
    }

    public void dfs(int[] nums, int idx, int target) {
        if (idx == nums.length) {
            if (sum == target) {res += 1;}
            return;
        }
        sum += nums[idx];
        dfs(nums, idx + 1, target);
        sum -= nums[idx];
        sum -= nums[idx];
        dfs(nums, idx + 1, target);
        sum += nums[idx];
    }
}
// 第二版
class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int n = nums.length, sum = 0;
        for (int i=0;i<n;i++) {
            sum += nums[i];
        }
        if (sum < Math.abs(target) || ((sum + target) & 1) == 1) {return 0;}
        int m = (sum + target) >> 1;
        int[][] f = new int[n+1][m+1];
        // 这是必要的,因为你之前都是求总和最大,所以i=0或者j=0的时候就是0,因为没得可装或者装不进去东西
        // 但现在是求方案数,所以没东西可装又j=0时候是1,也就是什么都不装
        // 但j要从0开始遍历,否则所有不装的方案都没记录下来
        f[0][0] = 1;
        // 注意这里不能直接这么初始化,因为可能nums数组有0元素,不一定体积为0时候不能装
        // for (int i=0;i<=n;i++) {f[i][0] = 1;}
        for (int i=1;i<=n;i++) {
            for (int j=0;j<=m;j++) {
                if (nums[i-1] > j) {f[i][j] = f[i-1][j];}
                else {f[i][j] = f[i-1][j] + f[i-1][j-nums[i-1]];}
            }
        }
        return f[n][m];
    }
}
相关推荐
LYFlied4 分钟前
【每日算法】LeetCode 25. K 个一组翻转链表
算法·leetcode·链表
Swizard9 分钟前
别再迷信“准确率”了!一文读懂 AI 图像分割的黄金标尺 —— Dice 系数
python·算法·训练
s090713613 分钟前
紧凑型3D成像声纳实现路径
算法·3d·声呐·前视多波束
可爱的小小小狼15 分钟前
算法:二叉树遍历
算法
d111111111d1 小时前
在STM32函数指针是什么,怎么使用还有典型应用场景。
笔记·stm32·单片机·嵌入式硬件·学习·算法
明洞日记1 小时前
【数据结构手册008】STL容器完全参考指南
开发语言·数据结构·c++
kingmax542120082 小时前
《数据结构C语言:单向链表-链表基本操作(尾插法建表、插入)》15分钟试讲教案【模版】
c语言·数据结构·链表
AI科技星2 小时前
质量定义方程常数k = 4π m_p的来源、推导与意义
服务器·数据结构·人工智能·科技·算法·机器学习·生活
摇摆的含羞草2 小时前
哈希(hash)算法使用特点及常见疑问解答
算法·哈希算法
Fine姐2 小时前
数据结构04——二叉树搜索树BST
数据结构