216. Combination Sum III
2017-03-26 21:50
211 查看
Combination Sum III
题目解析
代码实现
radix sort
就是在1~9中取k个数字,不能重复。使得k个数的和为n的组合存进数组并返回。
这里我使用的是暴力破解,根据最后一个数字的索引来迭代求和,如果到了尽头那么就把前一位的索引加一。如果前一位还是有进位,那么就继续进位,直到没有进位。然后把最后一位进位的索引后面的索引排在它的后面,然后往复进行。
改进前面的做法,使用夹逼来做这道题目,前后两个部分的数字数目一样,然后遇到条件一样的时候就把两个都做计算。使用这种方法结果是超时,当然这种做法确实有bug。
然后是DFS的做法,我们从9个数字中取k个数字,然后每个数字就是取或者没有取。这个代码的效率比第一种做法高了很多。
使用回溯,可以更加节约空间,但是速度上没有比DFS快,会差一点点。
原理类似桶排序,这里总是需要10个桶,多次使用
首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数
例如:
待排序数组[62,14,59,88,16]简单点五个数字
分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样
| 0 | 0 | 62 | 0 | 14 | 0 | 16 | 0 | 88 | 59 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
将桶里的数字顺序取出来,
输出结果:[62,14,16,88,59]
再次入桶,不过这次以十位数的数字为准,进入相应的桶,变成下边这样:
由于前边做了个位数的排序,所以当十位数相等时,个位数字是由小到大的顺序入桶的,就是说,入完桶还是有序
| 0 | 14,16 | 0 | 0 | 0 | 59 | 62 | 0 | 88 | 0 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
因为没有大过100的数字,没有百位数,所以到这排序完毕,顺序取出即可
最后输出结果:[14,16,59,62,88]
参考链接:http://www.cnblogs.com/kkun/archive/2011/11/23/2260275.html
题目解析
代码实现
radix sort
216. Combination Sum III
题目解析
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers. Example 1: Input: k = 3, n = 7 Output: [[1,2,4]] Example 2: Input: k = 3, n = 9 Output: [[1,2,6], [1,3,5], [2,3,4]]
就是在1~9中取k个数字,不能重复。使得k个数的和为n的组合存进数组并返回。
这里我使用的是暴力破解,根据最后一个数字的索引来迭代求和,如果到了尽头那么就把前一位的索引加一。如果前一位还是有进位,那么就继续进位,直到没有进位。然后把最后一位进位的索引后面的索引排在它的后面,然后往复进行。
代码实现
暴力破解:class Solution { public: __inline int calculateSum(vector<int> ind, int num) { int res = 0; for(int i = 1; i <= num; i++) res += ind[i]; return res; } vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> res; vector<int> ind(10, 0); if(k > 9 || n > 45) return res; for(int i = 1; i <= 9; i++) ind[i] = i; while(ind[1] <= 10 - k) { while(ind[k] <= 9) { int cur_sum = calculateSum(ind, k); if(cur_sum == n) res.push_back(vector<int>(ind.begin()+1, ind.begin()+k+1)); else if(cur_sum > n) { ind[k] = 10; break; } ind[k]++; } if(ind[1] == 10 - k) break; int stt = k-1; while(stt >= 1) { ind[stt] += 1; if(ind[stt] <= 10 + stt - k) break; else { stt--; } } for(int i = stt+1; i <= k; i++) ind[i] = ind[i-1] + 1; } return res; } };
改进前面的做法,使用夹逼来做这道题目,前后两个部分的数字数目一样,然后遇到条件一样的时候就把两个都做计算。使用这种方法结果是超时,当然这种做法确实有bug。
class Solution { public: __inline int calculateSum(vector<int> ind, int num) { int res = 0; for(int i = 1; i <= num; i++) res += ind[i]; return res; } vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> res; set<vector<int>> tmp; vector<int> ind(10, 0); vector<int> ind2(10, 0); if(k > 9 || n > 45) return res; int half = k >> 1, cnt = 1, cur_sum = 0; for(cnt = 1; cnt <= half + (1&k); cnt++) ind[cnt] = cnt; for(int i = 10 - half; i <= 9; i++) ind[cnt++] = i; queue<vector<int>> stk; stk.push(ind); while(!stk.empty()) { ind = stk.front(); stk.pop(); while(ind[half] < ind[half+1]) { int h1 = ind[half], h2 = ind[half+1]; ind2 = ind; while(ind[half] < ind[half+1]) { cur_sum = calculateSum(ind, k); if(cur_sum == n) { tmp.insert(vector<int>(ind.begin()+1, ind.begin()+k+1)); ind[half]++; ind[half+1]--; } else if(cur_sum > n) ind[half+1]--; else ind[half]++; } if(ind[k] - ind[1] <= k - 1) break; int stt = 0; if(cur_sum < n) { stt = half - 1; ind[half+1] = h2; while(stt >= 1) { ind[stt]++; if(ind[half+1] - ind[stt] >= half + 1 - stt) break; else stt--; } for(int i = stt+1; i <= half; i++) ind[i] = ind[i-1] + 1; } else if(cur_sum > n){ stt = half + 2; ind[half] = h1; while(stt <= k) { ind[stt]--; if(ind[stt] - ind[half] >= stt - half) break; else stt++; } for(int i = stt-1; i >= half+1; i--) ind[i] = ind[i+1] - 1; } else { // part 1 stt = half - 1; ind[half+1] = h2; while(stt >= 1) { ind[stt]++; if(ind[half+1] - ind[stt] >= half + 1 - stt) break; else stt--; } for(int i = stt+1; i <= half; i++) ind[i] = ind[i-1] + 1; // part 2 stt = half + 2; while(stt <= k) { ind2[stt]--; if(ind2[stt] - ind2[half] >= stt - half) break; else stt++; } for(int i = stt-1; i >= half+1; i--) ind2[i] = ind2[i+1] - 1; stk.push(ind2); } } } return vector<vector<int>>(tmp.begin(), tmp.end()); } };
然后是DFS的做法,我们从9个数字中取k个数字,然后每个数字就是取或者没有取。这个代码的效率比第一种做法高了很多。
class Solution { public: void backTrack(vector<vector<int>>&res, int target, int num, vector<int> &tmp, int stt) { int sz = tmp.size(), cur_sum = accumulate(tmp.begin(), tmp.end(), 0); if(tmp.size() == num) { if(cur_sum == target) res.push_back(tmp); return; } if(cur_sum >= target) return; if(9 - stt + 1 >= num - sz) { tmp.push_back(stt); backTrack(res, target, num, tmp, stt+1); tmp.pop_back(); backTrack(res, target, num, tmp, stt+1); } } vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> res; vector<int> ind; if(k > 9 || n > 45) return res; backTrack(res, n, k, ind, 1); return res; } };
使用回溯,可以更加节约空间,但是速度上没有比DFS快,会差一点点。
class Solution { public: void backTrack(vector<vector<int>>&res, int target, int num, vector<int> &tmp, int stt) { int sz = tmp.size(), cur_sum = accumulate(tmp.begin(), tmp.end(), 0); if(tmp.size() == num) { if(cur_sum == target) res.push_back(tmp); return; } if(cur_sum >= target) return; if(9 - stt + 1 >= num - sz) { for(int i = stt; i <= 9; i++) { tmp.push_back(i); backTrack(res, target, num, tmp, i+1); tmp.pop_back(); } } } vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> res; vector<int> ind; if(k > 9 || n > 45) return res; backTrack(res, n, k, ind, 1); return res; } };
radix sort
经典排序算法 - 基数排序Radix sort原理类似桶排序,这里总是需要10个桶,多次使用
首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数
例如:
待排序数组[62,14,59,88,16]简单点五个数字
分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样
| 0 | 0 | 62 | 0 | 14 | 0 | 16 | 0 | 88 | 59 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
将桶里的数字顺序取出来,
输出结果:[62,14,16,88,59]
再次入桶,不过这次以十位数的数字为准,进入相应的桶,变成下边这样:
由于前边做了个位数的排序,所以当十位数相等时,个位数字是由小到大的顺序入桶的,就是说,入完桶还是有序
| 0 | 14,16 | 0 | 0 | 0 | 59 | 62 | 0 | 88 | 0 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
因为没有大过100的数字,没有百位数,所以到这排序完毕,顺序取出即可
最后输出结果:[14,16,59,62,88]
参考链接:http://www.cnblogs.com/kkun/archive/2011/11/23/2260275.html
相关文章推荐
- LeetCode[216] Combination Sum III
- 216. Combination Sum III
- 216. Combination Sum III
- Java for LeetCode 216 Combination Sum III
- Leetcode 216 Combination Sum III 组合求和
- 216. Combination Sum III
- 216. Combination Sum III
- 216. Combination Sum III
- 216. Combination Sum III
- 216. Combination Sum III
- LeetCode216:Combination Sum III
- [leedcode 216] Combination Sum III
- 216. Combination Sum III
- LeetCode 216 Combination Sum III
- 216. Combination Sum III
- 216. Combination Sum III
- 216. Combination Sum III**
- leetcode 216 Combination Sum III java 算法
- 216. Combination Sum III
- 216. Combination Sum III