Eureka!

Keep thinking.

导航

组合序列

Posted on 2009-04-24 01:10  Kid.Loki  阅读(378)  评论(1编辑  收藏  举报

问题:从一个int数组array中选出m个数。

限制:1. array中元素互不相同;2. m不大于array的长度n。

思路:C(n,m) = C(n-1,m) + C(n-1,m-1)。考虑元素array[0]和子数列array[1..n-1],如果array[0]出现在结果中,那么就从array[1..n-1]中选出m-1个,否则从array[1..n-1]中选出m个。

代码:一种组合对应一个HashSet<Integer>,所有组合的集合构成一个HashSet<HashSet<Integer>>。

 1    public static HashSet<HashSet<Integer>> combination(int array[], int m){
 2        if(array == null || m > array.length) return null;
 3        return combination(array, m, 0);
 4    }

 5    
 6    private static HashSet<HashSet<Integer>> combination(int array[], int m, int start){
 7        HashSet<HashSet<Integer>> result_set = null;
 8        HashSet<Integer> hs = null;
 9        
10        // C(n,0)
11        if(m == 0){
12            result_set = new HashSet<HashSet<Integer>>();
13            result_set.add(new HashSet<Integer>());
14            return result_set;
15        }

16        
17        // C(n,1)
18        if(m == 1{
19            result_set = new HashSet<HashSet<Integer>>();
20            for(int i=start; i!=array.length; ++i) {
21                hs = new HashSet<Integer>();
22                hs.add(array[i]);
23                result_set.add(hs);
24            }

25            return result_set;
26        }

27        
28        // C(n,n)
29        if(m == array.length - start) {
30            result_set = new HashSet<HashSet<Integer>>();
31            hs = new HashSet<Integer>();
32            for(int i=start; i!=array.length; ++i)
33                hs.add(array[i]);
34            result_set.add(hs);
35            return result_set;
36        }

37        
38        // C(n,m) = C(n-1,m) + C(n-1,m-1)
39        HashSet<HashSet<Integer>> set1 = combination(array, m-1, start+1);
40        HashSet<HashSet<Integer>> set2 = combination(array, m, start+1);
41        for(HashSet<Integer> s : set1) s.add(array[start]);
42        for(HashSet<Integer> s : set2) set1.add(s);
43        
44        return set1;
45    }

 讨论

1. 元素互异的限制可放宽,把HashSet换成别的,例如ArrayList。

2. int型的限制可放宽,搞个泛型吧,很cool。

3. 时间复杂度怎么算?一眼看不出来,改天再深究。

4. 对返回void且在方法体内调用println的做法比较反感,情愿用集合之集合来存储结果。

5. 对非递归算法无爱并敬而远之,始终认为那是牛们为了戏虐猪羊而写的。