博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
377. Combination Sum IV
阅读量:5324 次
发布时间:2019-06-14

本文共 2274 字,大约阅读时间需要 7 分钟。

这个题的思路是动态规划,DP[n]代表能组成n的组合数。算1-n就可以,因为都是正数。

算dp[n]的时候遍历num[1] to num[n] index = i

如果i < dp[n] 那么dp[n] = dp[n] + dp[n-i]

从逻辑上来考虑比较复杂,比如4=0+4 1+3 2+2 3+1 4+0

0+4 1 (1+1+1+1)

1+3 1的组合3的组合
2+2 2的组合
2的组合
3+1 3的组合*1的组合
4+0 1 (4)

1+4+4+4+1 然后除以2 因为重复了一遍

但是结果似乎不对

看答案 算法是

dp[n] = dp[n] + dp[n-i]

比如4
从1遍历到4
1<4
dp[4] = dp[4] + dp[4-1]

public int combinationSum4(int[] nums, int target) {        int[] dp = new int[target+1];        dp[0] = 1;                for(int n = 1; n < target+1;n++)        {            for(int m = 0; m < nums.length;m++)            {                if(n >= nums[m]) dp[n] = dp[n] + dp[n-nums[m]];            }        }                return dp[target];    }

代码很简单,但是发现这种逻辑很难,比如我就觉得无从下手。。

感觉DP的题重点是找到动态规划的递推式,已经习惯于DP[N]从dp[n-1]来找

这个题就不是。。

递推式dp[n] = dp[n] + dp[n-i]


二刷:

一开始先排序,然后因为1,3和3,1这种都算有效,所以滑动窗口之类的没有意义。

而且,还有错,不能有效break。

看一刷的答案,发现是动态规划。

当时不理解,现在理解了。

public int combinationSum4(int[] nums, int target)     {        Arrays.sort(nums);        int[] dp = new int[target+1];        dp[0] = 1;                for(int i = 1; i <=target;i++)        {            for(int j = 0; j < nums.length; j++)            {                if(i - nums[j]>=0) dp[i] = dp[i] + dp[i - nums[j]];                else break;            }        }                return dp[target];    }

然后改进了一下,先排序,可以有效break,比直接遍历快一点点,而且好理解。

理解容易,不一定能想出来。

一开始有那个点意思,想到的是方法是递归。比如(nums[],target = 4
递归就变成(nums[],target-nums[n])
仔细想想应该就是动态规划的思路,然后通过DP来减少重复计算。

DP的双For loop大概可以总结为 i = 1 ~ n; j = 0 ~ i,从左边开始的话。

右边开始是 i = n~0; j = n~n-i???

------


三刷。

照着刚才的惯性DFS结果TLE了,做的时候就觉得不对……

应该是DP。。

dp[i]代表:

和是i的组合有多少种 的dp[4] = 1 + dp[3]

4 = 1 + 3

4 = 2 + 2
4 = 3 + 1

A + B的时候前面的A是nums里的数, 后者是可以组成B的左右组合,不能是dp[1] + dp[3]这样的话就重复计算了.

dp[1] + dp[2] 和 dp[2] + dp[1]计算了2次1+1+1...,这就是为啥一刷的办法不对。

Time: O(nk)

Space: O(k)

public class Solution {    public int combinationSum4(int[] nums, int target) {        if (nums.length == 0) return 0;        Arrays.sort(nums);        int[] dp = new int[target+1];        dp[0] = 1;                for (int i = 1; i <= target; i++) {            for (int j = 0; j < nums.length; j++) {                if (i - nums[j] >= 0) dp[i] += dp[i - nums[j]];                else break;            }        }        return dp[target];    }}

转载于:https://www.cnblogs.com/reboot329/p/5875877.html

你可能感兴趣的文章
CDH版本大数据集群下搭建的Hue详细启动步骤(图文详解)
查看>>
巧用Win+R
查看>>
浅析原生js模仿addclass和removeclass
查看>>
Python中的greenlet包实现并发编程的入门教程
查看>>
java中遍历属性字段及值(常见方法)
查看>>
深入理解jQuery框架-框架结构
查看>>
YUI3自动加载树实现
查看>>
python知识思维导图
查看>>
当心JavaScript奇葩的逗号表达式
查看>>
App Store最新审核指南(2015年3月更新版)
查看>>
织梦MIP文章内容页图片适配百度MIP规范
查看>>
点击复制插件clipboard.js
查看>>
[Kali_BT]通过低版本SerialPort蓝牙渗透功能手机
查看>>
C语言学习总结(三) 复杂类型
查看>>
HNOI2018
查看>>
【理财】关于理财的网站
查看>>
Ubunt中文乱码
查看>>
《当幸福来敲门》读后
查看>>
【转】系统无法进入睡眠模式解决办法
查看>>
省市县,循环组装,整合大数组
查看>>