My code:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<List<Integer>> combine(int n, int k) {
ArrayList<List<Integer>> result = new ArrayList<List<Integer>>();
if (n <= 0 || k <= 0 || k > n)
return result;
ArrayList<Integer> sample = new ArrayList<Integer>();
combine(1, n, k, sample, result);
return result;
}
private void combine(int begin, int end, int k, ArrayList<Integer> sample, ArrayList<List<Integer>> result) {
if (k <= 0)
result.add(new ArrayList<Integer>(sample));
else {
for (int i = begin; i <= end; i++) {
sample.add(i);
combine(i + 1, end, k - 1, sample, result);
sample.remove(sample.size() - 1);
}
}
}
public static void main(String[] args) {
Solution test = new Solution();
System.out.println(test.combine(5,3));
}
}
My test result:
好久没有做题了。。。十天。等等说。
这道题目着实不错啊。思路到现在也是精神上理解了下。
其实就是。比如 5, 3
那么一开始,
1, 2, 3 进袋。
然后 有个删除成员的细节操作,所以又变为,
1, 2 继续for 循环
然后 i = 4. 于是。
1, 2, 4 进袋。
1, 2, 5. 进袋。
然后for循环结束。整个函数结束,跳转到上一个递归处。即。
1, 然后插入2.
于是,删除2,继续for循环。
插入3, 于是
1, 3, 继续递归。。
以此类推。
我之前的确一直有这样的迷惑。
ArrayList, Queue, Stack 这些可以存储数据的包类,该如何在递归思想中保证其唯一性。
比如。
ArrayList a;
recursion(5, a);
...
当此处继续对a进行操作时,a的内容已经发生了变化。可能多了一些元素,也可能少了一些元素。因为他是和递归中的那些ArrayList 引用指向的同一个内存块。所以是统一的。
所以这段代码有个细节。
if (k <= 0)
result.add(new ArrayList<Integer>(sample));
为什么要新new一个ArrayList对象呢?因为储存在result这个范围内的仍然是指针,指向sample的那个内存块。如果不新new一个然后把原内容拷贝进来,那么就是仍指向原内存。那么存储的所有的指针都是指向同一个内存块sample,然后打印出来的内容都是sample最后状态的内容。所以必须先new一个。
这个算法还是一如既往的细致,灵巧。赞!
好久没刷题了。一恍惚,十天过去了,本来这十天可以干很多事的。算了,暑假在家没有怎么休息过,之前的确过于认真了,就算放松这十天吧。
哎,马上就要走了,没想到,在英国期盼的这些事,
见到爸妈然后狂吃美食,毕业典礼和同学的狂欢,和丹妮碰面一起旅行,和童年的小伙伴一起聚聚。。。这些事,这些盼了半年的事,这些一想起来就激动不已的事,竟然就这么过去了。
其实很多都做得还不够好,玩的不够尽兴。尤其是毕业典礼。刚回校三天,刚适应同学的体温,学校就强制离校了。
和丹妮,时间实在是太短了,短的我想带她去各处玩却发现哪个地方时间都是那么的紧。你至少给我十天啊,老天。??
这个世界上有条路,叫做, California State Route 1. I hope I can drive you through this long road, my girl, away from anything, everything, just you, and me.
爸妈的话,我内心是无比爱他们的,但是总觉得说出来肉麻,然后说不出来。有时候还故意气气他们,但他们的确为了做了太多太多。
昨天老爸50岁生日,但是过得很简单,就我和我妈陪着他,我们三个人。
他对我提出了他的要求,
第一,留学在外,人身安全第一位,绝对要注意安全,维护身体健康。
第二,要做一个让爸妈说起来觉得骄傲的儿子。
我会,努力去做到的,为了你们,也为了我。
今天去和表哥还有他女朋友吃了一顿饭,挺好的,我对她也挺满意的。心里不知道为什么,挺高兴的,好久没这么高兴了。也许他是我内心中,认为的,很重要很重要的人吧。
但是表哥工作最近被辞了,然后还没找到工作,这个事也一直瞒着那个姑娘,毕竟表哥条件不是很好,人家姑娘已经很好了,如果知道他现在没了工作,对于,结婚,还是会犹豫一些吧。所以瞒着她,打算先找到工作再说。
从小到大,我总觉得,因为一些自己弱的原因而去隐瞒,而去骗人,给自己所带来的屈辱,远比把这种弱的原因暴露出来更加让人感到羞耻。我一直记得小时候考得不好,别人问我成绩,我妈想撒撒谎,要点面子,但我爸就坚决不同意,就是得说真的。
我真觉得,这是一个好习惯。
一个连自己弱点都无法正视的人,又谈何奋发去改变这些弱点呢?
哎,想说的还有好多,我还是很怀念英国的日子,真的太美好了。
有机会,我一定要把那些写成一篇文章,发在这里。QQ空间实在是不太好意思发文章了,否则别人会觉得我又情绪泛滥了。
奈何,我就是个情绪泛滥的人。这算不算,不敢正视自己的弱点。
哈哈,我觉得,根本不算。
对了,给那个美国朋友写去的邮件还没回,不正常。估计是给我里面一段描写我对资本主义理解的文章所激怒了吧。哈哈。希望不是。还想着感恩节去他家做客呢。
**
总结:递归,Array, 如何保证递归中ArrayList的统一性。
**
Anyway, Good luck, Richardo!
My code:
public class Solution {
public List<List<Integer>> combine(int n, int k) {
ArrayList<List<Integer>> ret = new ArrayList<List<Integer>>();
if (n <= 0 || k <= 0 || k > n) {
return ret;
}
helper(1, k, n, ret, new ArrayList<Integer>());
return ret;
}
private void helper(int begin, int k, int n, List<List<Integer>> ret, List<Integer> group) {
if (group.size() > k) {
return;
}
else if (group.size() == k) {
ret.add(new ArrayList<Integer>(group));
return;
}
else {
if (begin > n) {
return;
}
else {
for (int i = begin; i <= n; i++) {
group.add(i);
helper(i + 1, k, n, ret, group);
group.remove(group.size() - 1);
}
}
}
}
}
差不多的做法。
Combination 还有一种更高效的解法:
public class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> ret = new ArrayList<List<Integer>>();
if (k < 0 || k > n) {
return ret;
}
else if (k == 0) {
ret.add(new ArrayList<Integer>());
return ret;
}
else {
ret = combine(n - 1, k - 1);
for (List<Integer> list : ret) {
list.add(n);
}
ret.addAll(combine(n - 1, k));
return ret;
}
}
}
复杂度应该都在 O(n!) 左右。
这个做法的思想就是。
对于一个数,他只有两种情况:
要么在 combination 中,
要么不在。
combine(n - 1, k - 1) 算出在的情况,然后统一加入 n
combine(n - 1, k) 算出不在的情况,直接插入ret
Anyway, Good luck, Richardo! -- 08/06/2016