组合算法面试题
来源:互联网 发布:西安移动网络怎么样 编辑:程序博客网 时间:2024/05/29 19:11
组合算法题往往有多个变种,如求一个集合的全部子集以及部分组合问题,这篇文章对这些常见的面试题做个汇总,权当做个记录,以免自己哪天忘了,难得到网路上去找。
一、求一个集合的全部子集
题目:给定一个集合s={a, b, c, d},试给出一个算法输出该集合的除了空集之外的全部子集。
分析:我们知道,一个集合的子集数目跟它的元素数目有关,集合元素数目为n,则子集数目为2^n。如包含两个元素的集合s1 = {a, b},则它的子集有:空集、{a}、{b}、{a, b}一共四个。求子集问题即从包含n个元素的集合中选取m个元素的问题,m可以是1...n。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。实现代码如下:
void Combination(char* string){ if(string == NULL) return; int length = strlen(string); vector<char> result; for(int i = 1; i <= length; ++ i) { Combination(string, i, result); //从strng中选择i个字符,结果保存在result中 }} void Combination(char* string, int number, vector<char>& result){ if(number == 0) { vector<char>::iterator iter = result.begin(); for(; iter < result.end(); ++ iter) printf("%c", *iter); printf("\n"); return; } if(*string == '\0') return; result.push_back(*string); //选择当前字符 Combination(string + 1, number - 1, result); result.pop_back(); //不选当前字符 Combination(string + 1, number, result);}
求子集还有一个更简单的算法,就是使用二进制。将数字从1——2^n-1循环,哪个位置位就选择。假定集合字符为{a, b ,c },则
001 a
010 b
011 a b
...
依次类推就可。代码如下:
void comb(char *str) { int len = strlen(str); //字符串长度,如str = “abc”长度为3 int max = 1 << len; //字符串自己的数目,如"abc"子集数目为8 for (int i=1; i<max; i++) { //输出所有子集,这里除去空集,所以从i=1开始输出 int k = i; int index = 0; while (k > 0) { if (k & 1) { cout << str[index] << " "; } k >>= 1; index++; } cout << endl; //每次输出一个子集换行 }}
二、人民币问题
题目:人民币有1元、2元、5元、10元、20元、50元、100元面值,试给出一个算法找出和为100的人民币组合(不包括100本身)。比如2张50的,或者2张50+2张20+1张10等。
分析:该题目与上面问题类似,可以采用组合的思路来解决。代码如下:
/* * rmb.cpp * * Created on: 2012-8-28 * Author: shusheng */#include <iostream>using namespace std;#define N 6int w[N];int number_used[N];bool is_used[N];int countnum = 0;void init() {w[0] = 1;w[1] = 2;w[2] = 5;w[3] = 10;w[4] = 20;w[5] = 50;for (int i = 0; i < N; i++) {number_used[i] = 0;}}void rmb(int start_index, int left_weight) {if (left_weight == 0) {for (int i = 0; i < N; i++) {if (number_used[i] > 0)cout << w[i] << "元: " << number_used[i] << "张 ";}cout << endl;countnum++;return;}for (int i = start_index; i < N; i++) {if (left_weight >= w[i]) {number_used[i]++;rmb(i, left_weight - w[i]);number_used[i]--;}}}int main() {init();rmb(0, 100);cout << countnum << endl;return 0;}函数rmb(start_index, left_weight)的功能定义是从start_index开始选择,输出最终和为left_weight的所有钱币组合。这里类似于完全背包问题,即每一样钱币都可以选择多次,而背包容量大小为100,每样物品的价值就是钱币面值,只是这里不是求最大值,而是总的组合数目。
当然这里的代码可以修改成另外一种形式,也许更好理解,如下所示:
void rmb(int start_index, int left_weight){ if (left_weight == 0) { for (int i = 0; i < N; i++) { if (number_used[i] > 0) cout << w[i] << "元: "<< number_used[i] <<"张 "; } cout << endl; return; } for (int i = start_index; i < N; i++) { int y = left_weight; while (y >= w[i]) { number_used[i]++; y -= w[i]; rmb(i+1, y); } number_used[i] = 0; }}这里的代码for循环中就是先从1元开始选,这种情况完成后,再从5元开始选(即最小钱币值为5),再是10、20等。
三、整数分解问题
给定一个正整数,试输出所有的分解。如5=1+1+1+1+1 = 1+1+1+2=1+1+3=1+2+2=1+4
其实这个问题也可以参照上面的人民币的例子,只是这里的数组取值改成了1,、2、3、4...n-1。当然此题应该还有更好的解法,暂时以这个思路写一下:
#include <iostream>#include <vector>using namespace std;#define NUMBER 10 //要分解的数为10static int cnt = 0; //分解数目vector<int> part; //用于存储分解结果void generate_partition(int x, int i, int v[]){ if (x == 0) { //输出 cout << ++cnt << ": "; for (int j=0; j<part.size(); j++) { cout << part[j] << " "; } cout << endl; return; } for (int j=i; j<NUMBER-1; ++j) { //输出逻辑是先输出包含1个v[j]的,然后是2个v[j]的... int select = v[j]; int c = 0, y=x; while (y >= select) { part.push_back(select); y -= select; c++; generate_partition(y, j+1, v); } while (c--) part.pop_back(); }}int main(){ int x = NUMBER; int v[NUMBER-1]; for (int i=0; i<NUMBER-1; i++) v[i] = i+1; generate_partition(x, 0, v); return 1;}
参考资料
http://zhedahht.blog.163.com/blog/static/2541117420114172812217/
http://blog.csdn.net/yysdsyl/article/details/4215232
- 组合算法面试题
- 组合算法面试题
- 面试题精选(62):组合算法
- 微软面试题 组合排列算法
- 面试题精选(64):元素可重复组合算法
- 程序员面试题精选100题-字符串的组合[算法]
- 程序员面试题精选100题(59)-字符串的组合[算法]
- Java算法面试题
- Java算法面试题
- 算法面试题
- 微软算法面试题
- 面试题算法题
- 算法面试题总结
- 单链表算法面试题
- 算法面试题
- 算法面试题一
- 算法面试题二
- 算法面试题三
- mysql 时间与日期函数与不求人
- C++操作SQLite示例笔记
- C常见问题之fopen的读写模式参数
- ABAP中的Table Control编程(2)
- EMC DFS 出现com.emc.documentum.fs.rt.AuthenticationException 错误解决方式
- 组合算法面试题
- 用yum下载rpm包
- ORACLE9I DATAGUARD 部署
- Scrum迭代中的质量标准
- struct union 内存分配
- 破解人脑 盗梦不再是科幻
- SAP中寻找增强的实现方法
- tomcat部署
- CDC::BitBlt用法