K SUM

My Submissions

http://www.lintcode.com/en/problem/k-sum/ 题目来自九章算法

13%

Accepted

Given n distinct positive integers, integer k (k <= n) and a number target.

Find k numbers where sum is target. Calculate how many solutions there are?

Example

Given [1,2,3,4], k=2, target=5. There are 2 solutions:

[1,4] and [2,3], return 2.

Tags Expand

SOLUTION 1:

唉妈,主页君做这题搞了2,3小时差点吐血。不过,做出来还是很爽嘀!
取自黄老师(九章算法)的思想:
后面的优化主页君没有管。 F[0][0][0]表示在一个空集中找出0个数,target为0,则有1个解,就是什么也不挑嘛!
其实应该这样写,也就是说,找0个数,目标为0,则一定是有1个解:

if (j == 0 && t == 0) {
  // select 0 number from i to the target: 0
  D[i][j][t] = 1;
}

1. 状态表达式:

D[i][j][t] = D[i - 1][j][t];
if (t - A[i - 1] >= 0) {
D[i][j][t] += D[i - 1][j - 1][t - A[i - 1]];
}

意思就是:

(1)我们可以把当前A[i - 1]这个值包括进来,所以需要加上D[i - 1][j - 1][t - A[i - 1]](前提是t - A[i - 1]要大于0)

(2)我们可以不选择A[i - 1]这个值,这种情况就是D[i - 1][j][t],也就是说直接在前i-1个值里选择一些值加到target.

代码:

 1 /**
 2      * @param A: an integer array.
 3      * @param k: a positive integer (k <= length(A))
 4      * @param target: a integer
 5      * @return an integer
 6      */
 7     public int  kSum1(int A[], int k, int target) {
 8         // write your code here
 9         if (target < 0) {
10             return 0;
11         }
12
13         int len = A.length;
14
15         int[][][] D = new int[len + 1][k + 1][target + 1];
16
17         for (int i = 0; i <= len; i++) {
18             for (int j = 0; j <= k; j++) {
19                 for (int t = 0; t <= target; t++) {
20                     if (j == 0 && t == 0) {
21                         // select 0 number from i to the target: 0
22                         D[i][j][t] = 1;
23                     } else if (!(i == 0 || j == 0 || t == 0)) {
24                         D[i][j][t] = D[i - 1][j][t];
25                         if (t - A[i - 1] >= 0) {
26                             D[i][j][t] += D[i - 1][j - 1][t - A[i - 1]];
27                         }
28                     }
29                 }
30             }
31         }
32
33         return D[len][k][target];
34     }

View Code

SOLUTION 2:

我们可以把最外层的Matrix可以省去。

这里最优美的地方,在于我们把target作为外层循环,并且从右往左计算。这里的原因是:

D[i][j][t] += D[i - 1][j - 1][t - A[i - 1]];

这个表达式说明D[i][j][t]是把上一级i的结果累加过来。这里我们省去了i这一级,也就是说在D[j][t]这个表里就地累加。而且t - A[i - 1]小于t。

在以下图表示就是说D[j][t]是来自于上一行的在t左边的这些值中挑一些加起来。

所以我们就必须从右往左逐列计算来避免重复的累加。

1. 如果你从左往右按列计算,每一列会被重复地加总,就会有重复计算。我们可以想象一下,len = 0为上表,len = 1为下表。

现在我们只有一个表,就是下面这个(因为第一个维度被取消了),现在如果你从左往右计算,被sum的区域会被填掉,覆盖

len = 0 那张表留下的值,下一个值的计算就不会准确了。

2. 或者如果你逐行计算,也是不可以的。因为你也是把生成D[j][t](在图里写的是D[i][j])的被sum的区域覆盖,也会造成结果不准确。

3. 所以,只要我们逐列计算,并且顺序是从右往左,即使我们只有一个二维表,我们的被sum区域也可以保持洁净,从空间角度来想,

就相当于从len=0那张表中取值。

总结:这种思维方式可能在面试里很难遇到,不过,可以开拓我们思维,这里同样是动规时如果取得上一级的值的问题,并且它考虑了省

去一级,就地利用二维空间的值,那么就要考虑我们上一级的旧表不要被覆盖。可以在大脑中构思一个三维空间,一个三维表由多个二维

表构成,如果把它们用一个表来做,再思考一下即可。

 1 // 2 dimension
 2     public int  kSum(int A[], int k, int target) {
 3         // write your code here
 4         if (target < 0) {
 5             return 0;
 6         }
 7
 8         int len = A.length;
 9
10         // D[i][j]: k = i, target j, the solution.
11         int[][] D = new int[k + 1][target + 1];
12
13         // only one solution for the empty set.
14         D[0][0] = 1;
15         for (int i = 1; i <= len; i++) {
16             for (int t = target; t > 0; t--) {
17                 for (int j = 1; j <= k; j++) {
18                     if (t - A[i - 1] >= 0) {
19                         D[j][t] += D[j - 1][t - A[i - 1]];
20                     }
21                 }
22             }
23         }
24
25         return D[k][target];
26     }

View Code

https://github.com/yuzhangcmu/LeetCode/blob/master/lintcode/dp/KSum.java

lintcode: k Sum 解题报告相关推荐

  1. [LintCode]k Sum

    题目 Given n distinct positive integers, integer k (k <= n) and a number target. Find k numbers whe ...

  2. Lintcode: k Sum II

    Given n unique integers, number k (1<=k<=n) and target. Find all possible k integers where the ...

  3. hdu 1003 Max Sum 解题报告

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 Problem Description Given a sequence a[1],a[2],a[3 ...

  4. 解题报告(一)B、(CF453D) Little Pony and Elements of Harmony(FWT经典套路 + 任意模数 k 进制FWT + 快速幂)(2)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  5. LeetCode 167.Two Sum II 解题报告

    LeetCode 167.Two Sum II 解题报告 题目描述 Given an array of integers that is already sorted in ascending ord ...

  6. hdu 2058 解题报告 - The sum problem

    hdu 2058 解题报告 - The sum problem 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2058 等差求和公式: Sn=(a1+aN ...

  7. 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)

    [LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...

  8. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  9. 解题报告(三)多项式求值与插值(拉格朗日插值)(ACM / OI)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

最新文章

  1. 网站推广——企业网站如何在网站推广中获取用户信任感?
  2. C语言程序设计 计算个人所得税 浙大版,《C语言及程序设计》实践参考——个人所得税计算器switch语句版...
  3. java 的 System.getenv() 和 System.getProperty()
  4. linux6.5声卡驱动安装,详解CentOS 6.5如何安装Realtek无线网卡驱动
  5. drbd实现mysql地热备_heartheartbeat+drbd+mysql主库热备
  6. ubuntu安装完mysql无法登录_Ubuntu安装mysql8后无法登陆怎么解决
  7. 网页空间 - 概念篇
  8. 怎么强制弹出窗口永远在最前面
  9. 谈谈我在自然语言处理进阶上的一些个人拙见
  10. 设置session时间 php,php中设置session过期时间方法
  11. 递归算法经典实例小结(C#实现)
  12. Android开发 SpannableString开发详解
  13. 电影特效是计算机专业吗,像那种专门为电影做特效的电脑最起码要达到什么样的配置呢?...
  14. 邓俊辉数据结构与算法学习笔记-第四章
  15. MBA教学目标、内容和方法
  16. 保险怎么买?有哪些销售渠道?各自的优缺点是什么?
  17. 工会优秀工作者先进事迹材料【加精推荐】 - 蒋炳楠的博客
  18. 手机互动网页项目总结(转)
  19. Android版APP全新上线,12306订票App更新3.0版本 Android系统已上线
  20. 一天一天学做外挂@第六天-去伪存真做筛选[武林外传]

热门文章

  1. 一文看尽腾讯WE大会:从治愈白血病到地球肿块,再到类脑芯片,烧脑探索“小宇宙”...
  2. HttpServletRequest HttpServletResponse ServletException 重新打开后报红解决方法
  3. Photoshop激活教程
  4. OS X 下在代码中枚举所有进程的方法
  5. 为何大多数人做出来的图表只是一坨屎?
  6. 【08】Effective Java - 异常
  7. java ADT生成带签名的apk
  8. 重写修改重写的Dialog显示问题
  9. jsf如何通过按钮切换在同一个页面上的非公共部分显示不同的内容
  10. js动态生成div和事件