DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • Array

    • 数组
    • 二分查找
    • moveZeros
  • Dynamic-programming

    • 动态规划
  • 刷题指南
  • String

    • 字符串
  • bitwise-operator

    • 位运算符
  • heap
  • history

    • [1014] 最佳观光组合
    • [1022] 从根到叶的二进制数之和
    • [104] 二叉树的最大深度
    • [11] 盛最多水的容器
    • [110] 平衡二叉树
    • [1227] 飞机座位分配概率
    • [129] 求根节点到叶节点数字之和
    • [1306] 跳跃游戏 III
    • [148] 排序链表
    • 155.最小栈
    • [165] 比较版本号
    • 1763. 最长的美好子字符串
    • [1870] 准时到达的列车最小时速
    • [199] 二叉树的右视图
    • [21] 合并两个有序链表
    • 215.数组中的第 k 个最大元素
    • [2306] 公司命名
    • [234] 回文链表
    • [2516] 每种字符至少取 K 个
    • [316] 去除重复字母
    • [3171] 找到按位或最接近 K 的子数组
    • [322] 零钱兑换
    • [41] 缺失的第一个正数
    • [44] 通配符匹配
    • [494] 目标和
    • [509] 斐波那契数
    • [518] 零钱兑换 II
    • [62] 不同路径
    • [676] 实现一个魔法字典
    • 70 爬楼梯
    • [718] 最长重复子数组
    • [78] 子集
    • [82] 删除排序链表中的重复元素 II
    • [871] 最低加油次数
    • [88] 合并两个有序数组
    • [887] 鸡蛋掉落
    • 958.二叉树的完全性检验
    • [98] 验证二叉搜索树
    • [983] 最低票价
    • leetcode practice
    • 约瑟夫问题
    • 移除重复节点
  • linked-list

    • 706. 设计哈希映射
    • 链表
  • stack

    • stack
  • tree

    • Tree Traversal
    • 二叉树的最近公共祖先
    • 二叉树
    • 题目
  • leetCode 刷题
  • 回溯
  • 排序算法

[494] 目标和

回溯算法

details

递归式

var findTargetSumWays = function (nums, target) {
    let ans = 0;
    backtrack(0, 0);
    return ans;

    function backtrack(sum, index) {
        if (nums.length === index) {
            if (sum === target) {
                ans++;
            }
            return;
        }
        backtrack(sum + nums[index], index + 1);

        backtrack(sum - nums[index], index + 1);
    }
};

改成迭代写法

通过栈模拟

var findTargetSumWays = function (nums, target) {
    let ans = 0;
    let stack = [[0, 0]];
    while (stack.length > 0) {
        let [sum, i] = stack.pop();

        if (i === nums.length) {
            if (sum === target) {
                ans++;
            }
        } else {
            stack.push([sum + nums[i]], i + 1);
            stack.push([sum - nums[i]], i + 1);
        }
    }
};

时间复杂度 在这个实现中,backtrack 函数以深度优先的方式遍历 nums 的所有可能的组合,每个元素可以选择 + 或 - 的操作,因此存在 2 个选择。对于长度为 n 的数组,整个组合的数量为 2^n。这意味着:

  • 时间复杂度为 O(2n)O(2^n)O(2n),因为每个数字都可以选择加或减,生成所有可能的 2^n 种组合。

空间复杂度

  • 递归的深度会达到 n,因此最差情况下递归栈的 空间复杂度为 O(n)O(n)O(n)。

dfs

details
var findTargetSumWays = function (nums, target) {
    const size = nums.length;
    return dfs(size - 1, target);

    function dfs(i, t) {
        if (i < 0) {
            if (t === 0) return 1;
            return 0;
        }
        return dfs(i - 1, t - nums[i]) + dfs(i - 1, t + nums[i]);
    }
};

时间复杂度分析

  • 时间复杂度: O(2n)O(2^n)O(2n)
  • 空间复杂度: O(n)O(n)O(n)

记忆优化

var findTargetSumWays = function (nums, target) {
    const memo = new Map();

    return dfs(nums.length - 1, target);

    function dfs(i, t) {
        if (i < 0) {
            return t === 0 ? 1 : 0;
        }

        const key = `${i},${t}`;
        if (memo.has(key)) {
            return memo.get(key);
        }

        const result = dfs(i - 1, t - nums[i]) + dfs(i - 1, t + nums[i]);

        memo.set(key, result);
        return result;
    }
};

空间复杂度优化

dfs 改成 dp 数组,递归改成迭代 0 1 背包问题


Last Updated:
Contributors: rosendo
Prev
[44] 通配符匹配
Next
[509] 斐波那契数