题目: 求双色球的所有可能组合?
规则:红球32个,编号1~32;篮球16个,编号1~16。6个红球 + 1个篮球为1注,6个红球没有先后顺序。
本题重点在于从32个球里取6个球,其实就是求组合问题,至于篮球的选择则非常简单,下面主要集中解求组合问题。
最直接的想法是通过6重循环实现,代码如下:
1 void enum_combination_loops(vector<vector<int>>& candidates, int redCount = 32, int redSelectCount = 6){ 2 for (int i = 1; i <= redCount - redSelectCount + 1; i++) 3 for (int j = i + 1; j <= redCount - redSelectCount + 2; j++) 4 for (int k = j + 1; k <= redCount - redSelectCount + 3; k++) 5 for (int m = k + 1; m <= redCount - redSelectCount + 4; m++) 6 for (int n = m + 1; n <= redCount - redSelectCount + 5; n++) 7 for (int l = n + 1; l <= redCount; l++) 8 { 9 vector<int> tmp; 10 tmp.push_back(i); 11 tmp.push_back(j); 12 tmp.push_back(k); 13 tmp.push_back(m); 14 tmp.push_back(n); 15 tmp.push_back(l); 16 candidates.push_back(tmp); 17 } 18 }
那有没有更优的方法呢,因为是枚举问题,鄙人认为这已经是比较优的解法了,欢迎拍砖,欢迎指出更好的办法。
那这个能不能换一种写法呢,让代码看上去不那么恐怖(n重循环总是给人一种很恐怖的感觉,尽管有时是一种比较高效的解法),答案当然是有的,下面直接贴出代码:
1 void enum_combination_recursive(vector<vector<int>>& candidates, vector<int> candidate, int index, int totalCount, int others){ 2 if (index + others > totalCount + 1) 3 { 4 return; 5 } 6 if (others == 1) { 7 for (int i = index; i <= totalCount; i++) 8 { 9 vector<int> tmp(candidate); 10 tmp.push_back(i); 11 candidates.push_back(tmp); 12 } 13 14 return; 15 } 16 candidate.push_back(index); 17 enum_combination_recursive(candidates, candidate, index + 1, totalCount, others - 1); 18 candidate.pop_back(); 19 enum_combination_recursive(candidates, candidate, index + 1, totalCount, others); 20 }
但实际上递归的方法的时间消耗是更大的,毕竟每次递归操作会有函数地址及参数压栈出栈的时间消耗,下图实验结果显示确实递归方法会耗时不少:
本题考查的是代码编写能力,而不是问题解决能力,以更简洁的代码实现问题解是程序员的基本素养。