【编程练习】寻找和为定值的多个数

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;
}

注:我们设置flag背包,用来标注对应的n+1是否被选中,1表示被选中,0则表示未选中,每当满足m==n时,则输出一组解。程序容易产生逻辑bug的地方在于length的使用(读者可以思考一下为何需要全局变量length,而不是直接使用n来代替for循环)。

时间: 2024-08-08 06:06:05

【编程练习】寻找和为定值的多个数的相关文章

JavaScript实现从数组中选出和等于固定值的n个数_javascript技巧

现实生活中的问题,可能会抽象为这样一种数据模型: 从一个数组中挑选出几个数,让这几个数相加的和为指定的值. 大多数读者应该有过网购的经历,网购一般会有个凑单功能,假如读者买了70元的商品,但是必须满100元才能包邮,这时系统会自动推荐一些商品,加起来差不多就100块钱了. 系统如何确定推荐哪些商品呢?这其实就是刚刚提到的模型,我们可以把热销商品的价格放到一个数组中,然后利用算法,找出数组中哪些价格的和为30元. 废话少说,小菜给大家分享一个JavaScript版本的算法实现. 算法代码: fun

剑指offer之和为定值的两个数

题目描述: 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输入: 每个测试案例包括两行: 第一行包含一个整数n和k,n表示数组中的元素个数,k表示两数之和.其中1 <= n <= 10^6,k为int 第二行包含n个整数,每个数组均为int类型. 输出: 对应每个测试案例,输出两个数,小的先输出.如果找不到,则输出"-1 -1" 样例输入: 6 15 1 2 4 7 11 15 样例输出:

编程之美之二进制数中1的个数

问题: 对于一个字节(8bit)的变量,求其二进制中1的个数,要求算法的执行效率尽可能的高. 例如把9表示成二进制是1001,有2位是1,因此如果输入9,1的个数为2. 解法一: 可以举一个8位二进制的例子.对于二进制操纵,我们除以一个2,原来数字就会减少一个0(向右移一位).如果除的过程中有余,那么久表示当前位置有一个1. 以10100010为例: 第一次除以2时,商为1010001,余为0 第二次除以2时,商为101000,余为1 因此,考虑利用整形数据除法的特点,通过相除和判断余数的值进行

程序员面试资源大收集(转)

资源一:<crack the code interview>--谷歌资深技术面试官经典之作 本书的中文目录如下,大部分内容由Hawstein君原创翻译,部分缺失的由快课网Jay13补充. 1.1 判断一个字符串中的字符是否唯一 1.2 字符串翻转 1.3 去除字符串中重复字符 1.8 利用已知函数判断字符串是否为另一字符串的子串 2.1 从链表中移除重复结点 2.2 实现一个算法从一个单链表中返回倒数第n个元素 2.3 给定链表中间某结点指针,删除链表中该结点 2.4 求由两个链表结点组成的数

面向对象编程方式实现四则运算和计算矩形面积

用Javascript实现类似两个选项卡切换的效果,用面向对象编程的方式,实现四则运算和计算矩形面积: CatView.php: <html> <head> <meta http-equiv="content-type" content="text/html;charset=GBK" /> <script language="javascript"> <!-- function selType

pascal编程-使用pascal中的集合编程

问题描述 使用pascal中的集合编程 将自然数1到9这九个数分成三组,将每组的三个数字拼成三位数,每个数字不能重复,且每个三位数都是完全平方数.请找出这样的三位数. 解决方案 PASCAL 高级编程 解决方案二: http://bbs.cfan.com.cn/thread-1455458-1-1.html

C语言实现两个递减数列中寻找某一个数_C 语言

本文实例讲述了C语言实现两个递减数列中寻找某一个数的方法,分享给大家供大家参考之用.具体方法如下: 通常来说这道题算二分查找法中非常有难度的一题了. 题目如下: 一个数组是由一个递减数列左移若干位形成,比如{4, 3, 2, 1, 6, 5}是由{6, 5, 4, 3, 2, 1}左移两位,在这种数组中查找某一个数. 实现代码如下: int array[] = {4, 3, 2, 1, 6, 5}; const int size = sizeof array / sizeof *array; i

PDF、ZIP、DOC链接的标注

pdf|链接 原文:http://www.maratz.com/blog/archives/2005/01/13/pdf-links-labeling/翻译:http://www.176so.com/past/2007/3/17/pdf_links_labeling/ css技巧之PDF.ZIP.DOC链接的标注 有时候我们希望能明确的用小图标来标明我们的超链接的类型.是一个zip文档还是一个pdf文件.这样访问者就知道他所要点击的这个链接是下载而不是打开另一个页面了.如果所有的人都使用IE7或

产生下一个排列数的算法

全排序: 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列.当m=n时所有的排列情况叫全排列.例如n=3,全排序为:123.132.213.231.312.321共6种. 字典序法: 对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是:从左到右逐个比较对应的字符大小.字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列即:123.132.213.231.312.321. 1.现在假设输入全排序中的一串数字