力扣494
Posted zhangbochao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣494相关的知识,希望对你有一定的参考价值。
给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
- 数组非空,且长度不会超过20。
- 初始的数组的和不会超过1000。
- 保证返回的最终结果能被32位整数存下。
来源:力扣(LeetCode)
解法一:暴力(超时)
不贴代码了,求出全部可能性,并遍历,得到目标为S的数量。时间复杂度2的N次方。
解法二:递归
注意,初始的数组的和不会超过1000。这句话及其关键。定义一个数组,列号为nums数组的前几个数。行号为这几个数组合之和,值为这个值的数量。由于组合之和可能为负数,且范围在[-1000,1000],所以一共需要有2001行,第0行代表和为-1000。
递归关系式为
getRes(res,nums.length,S,nums)=getRes(res, length-1, s-nums[length-1],nums)+getRes(res, length-1, s+nums[length-1],nums)。
代码如下(注意要对行号进行判断,有可能溢出):
1 package Leetcode; 2 public class findTargetSumWays { 3 public int findTargetSumWays(int[] nums, int S) { 4 if(S>1000||S<-1000){return 0;} 5 int[][] res = new int[2001][2]; 6 7 res[nums[0]+1000][1]+=1; 8 res[-nums[0]+1000][1]+=1; 9 10 int count = getRes(res,nums.length,S,nums); 11 return count; 12 } 13 14 private int getRes(int[][] res, int length, int s,int[] nums) { 15 if(length==1){ 16 if(s>1000||s<-1000){return 0;} 17 return res[s+1000][1]; 18 } 19 int small = getRes(res, length-1, s-nums[length-1],nums); 20 int big = getRes(res, length-1, s+nums[length-1],nums); 21 return small+big; 22 } 23 }
解法三:dp
其实这道题dp和递归的思想是一样的,只是dp是从前往后推,递归是从后往前推。代码如下
1 class Solution { 2 public int findTargetSumWays(int[] nums, int S) { 3 int[][] dp = new int[nums.length][2001]; 4 dp[0][nums[0] + 1000] = 1; 5 dp[0][-nums[0] + 1000] += 1; 6 for (int i = 1; i < nums.length; i++) { 7 for (int sum = -1000; sum <= 1000; sum++) { 8 if (dp[i - 1][sum + 1000] > 0) { 9 dp[i][sum + nums[i] + 1000] += dp[i - 1][sum + 1000]; 10 dp[i][sum - nums[i] + 1000] += dp[i - 1][sum + 1000]; 11 } 12 } 13 } 14 return S > 1000 ? 0 : dp[nums.length - 1][S + 1000]; 15 } 16 }
以上是关于力扣494的主要内容,如果未能解决你的问题,请参考以下文章
2021-12-24:划分字母区间。 字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。 力扣763。某大厂面试