标签:
2010 年中兴面试题 
编程求解: 
输入两个整数n 和m,从数列1,2,3.......n 中随意取几个数, 
使其和等于m ,要求将其中所有的可能组合列出来。
// 21 题递归方法 
//copyright@ July && yansha 
//July、yansha,updated。 
#include<list> 
#include<iostream> 
using namespace std; 
list<int>list1; 
void find_factor(int sum, int n) 
{ 
// 递归出口 
if(n <= 0 || sum <= 0) 
return; 
// 输出找到的结果 
if(sum == n) 
{ 
// 反转list 
list1.reverse(); 
for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++) 
cout << *iter << " + "; 
cout << n << endl; 
list1.reverse(); 
} 
list1.push_front(n); //典型的01 背包问题 
find_factor(sum-n, n-1); //放n,n-1 个数填满sum-n 
list1.pop_front(); 
find_factor(sum, n-1); //不放n,n-1 个数填满sum 
} 
int main() 
{ 
int sum, n; 
cout << "请输入你要等于多少的数值sum:" << endl; 
cin >> sum; 
cout << "请输入你要从1.....n 数列中取值的n:" << endl; 
cin >> n; 
cout << "所有可能的序列,如下:" << endl; 
find_factor(sum,n); 
return 0; 
}
逻辑分析:
1、比起微软,google,百度这些公司,中兴的面试题还是略显逗比的,并非是说难度上差异,而是中兴的题目总是显得不伦不类。本题其实就是考察数的组合,对于此类问题,通常手段都是递归,而我们的目标就在于找出递归式。
2、问题其实本质上就是0/1背包问题,对于每一个n,我们采用贪婪策略,先考察是否取n,如果取n,那么子问题就变成了find(n-1,m-n),而如果舍弃n,子问题则为find(n-1,m)。至此,我们利用DP思想找到了递归式(很多时候,所谓动态规划,贪婪只是一念之差)。
3、那么,如何制定解的判定策略?我们知道,递归需要边界条件,而针对背包问题,边界条件只有两种,如果n<1或者m<1,那么便相当于“溢出”,无法combo出m,而另一种可能就是在剩余的n个里恰好满足m==n,即此时 背包刚好填充满,输出一组解单元。除此之外,再无其他。
C源码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int length;
void findCombination(int n,int m,int *flag)
{
	if(n < 1 || m < 1)
		return;
	if(n > m)
		n = m;
	if(n == m)
	{
		flag[n-1] = 1;
		for(int i=0;i<length;i++)
		{
			if(flag[i] == 1)
				printf("%d\t",i+1);
		}
		printf("\n");
		flag[n-1] = 0;
	}
	flag[n-1] = 1;
	findCombination(n-1,m-n,flag);
	flag[n-1] = 0;
	findCombination(n-1,m,flag);
}
int main()
{
	int n, m;
	scanf("%d%d",&n,&m);
	length = n;
	int *flag = (int*)malloc(sizeof(int)*length);
	findCombination(n,m,flag);
	free(flag);
	return 0;
}
标签:
原文地址:http://blog.csdn.net/wangyaninglm/article/details/44020487