leetcode-494 目标和,cache的选择
题目如上。
我们假定,求从 nums 数组第 flag 位置开始目标和为 S 的组合数的函数为:G(nums, S, flag) 。
那么状态转移方程的表示为:G(nums, S, flag) = G(nums,S-nums[flag],flag+1) + G(nums,S+nums[flag],flag+1) 。一个背包类问题。
递归表示很好实现:
public int recursion(int[] nums, int S, int flag){ if (flag == nums.length) { if (S == 0) { return 1; } return 0; } return recursion(nums,S-nums[flag],flag+1)+recursion(nums,S+nums[flag],flag+1); }
相应的,指数级时间复杂度,回归过程中存在非常多的重复计算。需要用缓存优化掉这些重复计算。
问题就在于,如果要建立缓存,缓存需要有两个维度:S 和 flag 。我们需要沿着这两个维度前进推演最终结果,但不能用简单的二维数组建立缓存。
因为 S 的取值范围是不固定的,最大值为 S 与 nums 中所有元素的和,最小值为 nums 中所有元素的差,且可能存在负值。
官方题解中,将 S 加 1000,使 S 全部映射到正数空间中。
但我认为,无论问题规模的大小,直接申请长度为 1000 的连续数组空间比较浪费,更倾向于一维数组结合哈希表的方式构建缓存。
nums 由一维数组存储,存储的元素为一张哈希表,哈希表中存储 nums 对应的 S 的解:
public int findTargetSumWays(int[] nums, int S) { if (nums == null) { return 0; } Map<Integer, Integer>[] dpCache = new Map[nums.length]; return dp(nums, S, 0, dpCache); } /** * @Author Nxy * @Date 2020/4/28 * @Description G(nums, S, flag) * G(nums,S-nums[flag],flag+1)+G(nums,S+nums[flag],flag+1) */ public int dp(int[] nums, int S, int flag, Map<Integer, Integer>[] dpCache) { if (flag == nums.length) { if (S == 0) { return 1; } return 0; } if (dpCache[flag] != null) { Map<Integer, Integer> map = dpCache[flag]; if (map.keySet().contains(S)) { return map.get(S); } int tempRe = dp(nums, S - nums[flag], flag + 1, dpCache) + dp(nums, S + nums[flag], flag + 1, dpCache); map.put(S, tempRe); return tempRe; } dpCache[flag] = new HashMap<Integer, Integer>(); int tempRe = dp(nums, S - nums[flag], flag + 1, dpCache) + dp(nums, S + nums[flag], flag + 1, dpCache); dpCache[flag].put(S, tempRe); return tempRe; }
当你看清人们的真相,于是你知道了,你可以忍受孤独
分类:
数据结构与算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构