简介:

动态规划问题面试中经常遇到的问题之一,按照动态规划的一般定义,其一般解法在于将大问题分解为很多小问题去解决,但是我在遇到很多实际的问题时,想法都是强行的去将问题分解,而忽略了分解的必要性和途径的合理性。看某知乎大佬的帖子:动态规划的核心思想在于分解的小问题能否被上一级的问题去重用,也就是说我们在将大问题分解为小问题时,要考虑到求解出的小问题对于大问题的求解是否有一定的作用而且求解小问题的过程对大问题需要没有任何影响(像不像封装,似乎好多理论都是大同小异的,核心思想都很相似)。

例子:

以LeetCode-Combination Sum IV问题为例:

题目是这样描述的:

Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example:

nums = [1, 2, 3]
target = 4 The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1) Note that different sequences are counted as different combinations. Therefore the output is 7. 是不是看起来感觉毫无难度,递归嘛,一层一层下去不就好了!所以我写出了递归求解思路:
 private int combinationSum4_recur(int[] nums, int target){
int sum = 0;
for(int i : nums){
if(i == target) sum += 1;
else if(i < target) sum += combinationSum4_recur(nums, target - i);
}
return sum;
}

和我们用脑子解决这个问题的思路一模一样,然后就TLE了。。。

出错的例子:nums={2,1,3} target=35,我日哦,如果用大脑去解决,你得想吐了。

所以我需要想想这是为什么,首先1+1,然后+1,然后+1.。。。。。然后好多好多+1,emmmm,出来了一个35的方案了,然后下一轮首先1+1,然后+1,然后+1.。。。。。然后好多好多+1再+3。等一下前面的1+1+1什么的是不是很熟悉!我们为什么不把它记住呢!所以,dp[]来了!

dp[]数组是什么呢,它是一个长度为target+1的int数组,首先,0为1;它的意思就是默认nums数组中组合为0的可能方式设定为1.然后,dp[1]等一系列元素我们暂时设置为-1,表示还未进行计算。这样,由顶而下的动态规划就出来了,我们将求解一个巨大的target分解为求解一个较小的target,而求解这个较小的target又会被分解为求解一个更小的target。。。。。。直到最后,而在这过程中,求解出来的target我们都存储在了dp数组中!那么求解到最后,我们岂不是一直进行数组的调用就可以了!只进行了很少的计算!代码如下:

 private int combinationSum4_dp(int[] nums, int target){
dp = new int[target + 1];
Arrays.fill(dp, -1);
dp[0] = 1;
return helper(nums, target);
} private int helper(int[] nums, int target){
/**
* dp记录到达索引指示的target有几种方案去解决
* 就是相当于记住它的中间结果!!!
*/
if (dp[target] != -1) {
return dp[target];
}
int res = 0;
for (int i = 0; i < nums.length; i++) {
if (target >= nums[i]) {
res += helper(nums, target - nums[i]);
}
}
dp[target] = res;
return res;
}

是不是清晰很多,我们首先进行了较小target的组合数,然后依次往大再往大。。。。。。这样到最后我们就解决了那个看似很大的target。这不就是动态规划的思想吗!

所以以后首先要找到大问题和小问题之间共有的特性,列出一定的状态转移规律,然后设计满足条件的小问题解决方案,最后凭借记忆中的中间值快速求出最终解!

当然动态规划问题极多,有待后续继续进步。。。。。。

动态规划,以LeetCode-CombinationSumIV问题为例的更多相关文章

  1. 【动态规划】leetcode - Maximal Square

    称号: Maximal Square Given a 2D binary matrix filled with 0's and 1's, find the largest square contain ...

  2. 动态规划 算法(DP)

    多阶段决策过程(multistep decision process)是指这样一类特殊的活动过程,过程可以按时间顺序分解成若干个相互联系的阶段,在每一个阶段都需要做出决策,全部过程的决策是一个决策序列 ...

  3. [leetcode]multiply-strings java代码

    题目: Given two numbers represented as strings, return multiplication of the numbers as a string. Note ...

  4. 【Leetcode】179. Largest Number

    Given a list of non negative integers, arrange them such that they form the largest number. For exam ...

  5. 动态规划1——最长递增子序列、最长公共子序列、最长公共子串(python实现)

    目录 1. 最长递增序列 2. 最长公共子序列 3. 最长公共子串 1. 最长递增序列 给定一个序列,找出其中最长的,严格递增的子序列的长度(不要求连续). 解法一:动态规划 通过一个辅助数组记录每一 ...

  6. leetcode常见算法与数据结构汇总

    leetcode刷题之后,很多问题老是记忆不深刻,因此特意开此帖: 一.对做过题目的总结: 二.对一些方法精妙未能领会透彻的代码汇总,进行时常学习: 三.总结面试笔试常见题目,并讨论最优解法及各种解法 ...

  7. SQL排名问题,100% leetcode答案大公开!

    (首先原谅我最近新番看多了,起了一个中二的名字) 最近在找实习,所以打算系统总结(复习)一下sql中经常遇到问题.不管是刷leetcode还是牛客的sql题,有一个问题总是绕不开的,那就是排名问题.其 ...

  8. lintcode:First Missing Positive 丢失的第一个正整数

    题目 丢失的第一个正整数 给出一个无序的整数数组,找出其中没有出现的最小正整数. 样例 如果给出 [1,2,0], return 3 如果给出 [3,4,-1,1], return 2 挑战 只允许时 ...

  9. 【概率DP入门】

    http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html 有关概率和期望问题的研究 摘要 在各类信息学竞赛中(尤其是ACM竞赛中) ...

随机推荐

  1. Ext--Layout(布局)

    EXT中的布局,常用的有border.column.fit.form.tabel这几种. Fit布局,子元素将自动填满整个父容器(对元素设置宽度无效),如果容器组件中有多个子元素,则只会显示第一个子元 ...

  2. js获取当前时间戳以及前一天时间戳

    js获取当前时间戳以及前一天时间戳(毫秒) var timestamp = (new Date()).getTime(); console.log(timestamp);//打印当前时间戳 conso ...

  3. HMM(隐马尔科夫)用于中文分词

    隐马尔可夫模型(Hidden Markov Model,HMM)是用来描述一个含有隐含未知参数的马尔可夫过程. 本文阅读了2篇blog,理解其中的意思,附上自己的代码,共同学习. 一.理解隐马尔科夫 ...

  4. JPA 一对多双向映射 结果对象相互迭代 造成堆栈溢出问题方法

    问题: JPA 在双向映射时,会相互包含对方的实例,相互引用,造成递归迭代,堆栈溢出(java.lang.StackOverflowError). 分析: 在后端向前端传递的时候会将数据序列化,转为j ...

  5. H3C ACL规则的匹配顺序

  6. springboot + redis + 注解 + 拦截器 实现接口幂等性校验

    一.概念 幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如: 订单接口, 不能多次创建订单 支付接口, 重复支付同一笔订单只能扣一次钱 支付宝回调接口, 可能会多 ...

  7. H3C 通配符掩码的应用示例

  8. linux I/O 内存分配和映射

    I/O 内存区必须在使用前分配. 分配内存区的接口是( 在 <linux/ioport.h> 定义): struct resource *request_mem_region(unsign ...

  9. js New一个函数和直接调用的区别

    使用New是构造函数,不使用New是函数调用,同时this指向不同. 示例: function Test(name, age, job) { console.log(this); this.name ...

  10. springBoot中使用使用junit测试文件上传,以及文件下载接口编写

    本篇文章将介绍如何使junit在springBoot中测试文件的上传,首先先阅读如何在springBoot中进行接口测试. 文件上传操作测试代码 import org.junit.Before; im ...