当前位置: 面试刷题>> 目标和 (经典算法题500道)


### 题目描述补充 **题目:目标和** 给定一个非负整数数组 `nums` 和一个整数 `target`,数组 `nums` 可以包含重复元素。请你判断是否存在一个子集,使得子集元素之和等于 `target`。请注意,数组中的元素可以重复使用。 **示例 1**: ``` 输入: nums = [1, 1, 1, 1, 1], target = 3 输出: True 解释: 数组 [1, 1, 1] 的和等于 3。 ``` **示例 2**: ``` 输入: nums = [1, 1, 1, 1, 1], target = 4 输出: False ``` ### 解题思路 这个问题可以使用动态规划(Dynamic Programming)或者回溯法(Backtracking)来解决。由于题目中允许元素重复使用,且我们关心的是是否存在子集的和等于 `target`,动态规划的方法在这里更为合适。 我们可以将问题转化为“背包问题”的一个变种,即考虑每个元素可以被选择多次,目标是填满一个容量为 `target` 的背包。 ### 动态规划解法(PHP、Python、JavaScript) #### PHP 示例代码 ```php function canPartition($nums, $target) { $sum = array_sum($nums); if ($sum < $target) return false; // 总和小于目标值,直接返回false if ($sum % 2 != $target % 2) return false; // 奇偶性不一致,无法构成目标和 $target = $sum - $target; // 转化为求是否存在和为sum/2的子集 $dp = array_fill(0, $target + 1, false); $dp[0] = true; // 初始化,和为0总是可以构成 foreach ($nums as $num) { for ($i = $target; $i >= $num; $i--) { $dp[$i] = $dp[$i] || $dp[$i - $num]; } } return $dp[$target]; } ``` #### Python 示例代码 ```python def canPartition(nums, target): total_sum = sum(nums) if total_sum < target: return False if total_sum % 2 != target % 2: return False target = (total_sum - target) // 2 dp = [False] * (target + 1) dp[0] = True for num in nums: for i in range(target, num - 1, -1): dp[i] = dp[i] or dp[i - num] return dp[target] ``` #### JavaScript 示例代码 ```javascript function canPartition(nums, target) { const sum = nums.reduce((a, b) => a + b, 0); if (sum < target) return false; if (sum % 2 !== target % 2) return false; target = Math.floor((sum - target) / 2); const dp = new Array(target + 1).fill(false); dp[0] = true; for (const num of nums) { for (let i = target; i >= num; i--) { dp[i] = dp[i] || dp[i - num]; } } return dp[target]; } ``` 以上三种语言的实现都遵循了相同的逻辑,即使用动态规划来解决这个问题。希望这些示例对你有所帮助,并欢迎访问码小课网站获取更多相关内容!
推荐面试题