算法练习:排列组合之组合和

算法练习:排列组合之组合和

问题描写叙述

给出一组不同的正整数序列和一个目标值,求出全部可能的组合,使得组合里全部元素和为目标值。

要求:

1)每一个组合里的元素依照升序排列。

2)输出组合里不含有反复的组合。

3)输入序列中的整数能够多次使用。

 

举例:

输入{2。3。4。7},目标值为7

输出{7}。{2。2,3}。{3,4}

 

问题分析

为了让输出元素按升序排列,可对输入序列进行排序。

同这里我们使用递归的方法来解决这个组合问题,即典型的for语句内调用递归函数。须要注意下面几点:

1)记录剩余目标值和,仅仅有当该值为0时。组合才是有效的。

2)记录当前位置,由于序列中的数能够反复使用,所下面一次递归时,还能够从当前位置開始。这将体如今递归函数的參数里。

详细可參看代码实现中的GetResultSet函数。

 

扩展问题

假设序列中可能有同样的元素。而且每一个元素最多仅仅能使用一次,那么又该怎么处理?相对于之前的问题,这里有两个变化:1)每一个元素最多仅仅能使用一次,下次递归时是不能从当前位置開始的,而是从下一个開始。2)因为序列中含有相等的元素,哪怕每一个元素最多仅仅使用一次,也可能出现反复的组合,所以。为了避免反复,仅仅取第一个同样元素。

详细可參看代码实现中的GetResultSetEx函数。

 

代码实现

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef vector<int> IntArray;
 

//结果集
typedef vector<vector<int>> ResultSet; 
ResultSet gResultSet;

//原始序列中不含同样的值
void GetResultSet( const IntArray& mSrcArray, int nTarget, 
				  IntArray& mDstArray, int iStart )
{
	if ( nTarget < 0 ) return;
	if ( nTarget == 0 )
	{
		//找到一个结果
		gResultSet.push_back( mDstArray );
	}
	else
	{
		for( int i = iStart; i < mSrcArray.size(); ++i )
		{
			//后面更大的数不可能满足条件
			if ( mSrcArray[i] > nTarget ) break;

			//增加当前元素
			mDstArray.push_back( mSrcArray[i] );

			//递归处理。由于元素能够反复使用,所以从当前位置继续递归
			GetResultSet( mSrcArray, nTarget-mSrcArray[i], mDstArray, i );

			//重置
			mDstArray.pop_back();
		}
	}
}

//序列中可能有同样的元素。而且每一个元素最多仅仅能使用一次。不含反复组合
void GetResultSetEx( const IntArray& mSrcArray, int nTarget, 
				  IntArray& mDstArray, int iStart )
{
	if ( nTarget < 0 ) return;
	if ( nTarget == 0 )
	{
		//找到一个结果
		gResultSet.push_back( mDstArray );
	}
	else
	{
		for( int i = iStart; i < mSrcArray.size(); ++i )
		{
			//后面更大的数不可能满足条件
			if ( mSrcArray[i] > nTarget ) break;

			//避免结果集反复。仅仅取第一个同样值增加结果中
			if ( i != iStart && mSrcArray[i] == mSrcArray[i-1] ) continue;

			//增加当前元素
			mDstArray.push_back( mSrcArray[i] );

			递归处理。由于元素能够反复使用,所以从当前位置继续递归
			//GetResultSet( mSrcArray, nTarget-mSrcArray[i], mDstArray, i );

			//递归处理,由于元素不能够反复使用,所以从下一位置继续递归
			GetResultSetEx( mSrcArray, nTarget-mSrcArray[i], mDstArray, i+1 );

			//重置
			mDstArray.pop_back();
		}
	}
}


//输出结果集
void OutPutResultSet()
{
	if ( gResultSet.size() <= 20 )
	{
		for( ResultSet::iterator it = gResultSet.begin(); 
			it != gResultSet.end(); ++it )
		{
			for( IntArray::iterator itTemp = it->begin(); 
				itTemp != it->end(); ++itTemp )
			{
				cout << *itTemp << " ";
			}
			cout << endl;
		}
		
	}
	cout << "总共结果数:" << gResultSet.size() << endl;
	cout << "---------------------------------------" << endl;
}


int main()
{
	IntArray mSrcArray;
	IntArray mDstArrayTemp;
	int nTarget = 0;
	
	while( true )
	{
		//构造源数据
		int nTemp = 0;
		mSrcArray.clear();
		while( cin >> nTemp )
		{
			if ( nTemp == 0 ) break;
			mSrcArray.push_back( nTemp );
		}
		cin >> nTarget;

		//从小到大排序
		sort( mSrcArray.begin(), mSrcArray.end() );

		mDstArrayTemp.clear();
		gResultSet.clear();
		//GetResultSet( mSrcArray, nTarget, mDstArrayTemp, 0 );
		GetResultSetEx( mSrcArray, nTarget, mDstArrayTemp, 0 );

		//输出结果
		OutPutResultSet();
	}
	return 0;
}

 算法练习:排列组合之组合和算法练习:排列组合之组合和

系列文章说明:
1.本系列文章[算法练习],不过本人学习过程的一个记录以及自我激励,没有什么说教的意思。

假设能给读者带来些许知识及感悟。那是我的荣幸。
2.本系列文章是本人学习陈东锋老师《进军硅谷。程序猿面试揭秘》一书而写的一些心得体会,文章大多数观点均来自此书,特此说明!

3.文章之中,难免有诸多的错误与不足,欢迎读者批评指正,谢谢.

作者:山丘儿
转载请标明出处。谢谢。

原文地址:http://blog.csdn.net/s634772208/article/details/46710405

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109171.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 新手编程入门先学什么?

    新手编程入门先学什么?编程入门先学什么?关于编程的基本语言,想学习的朋友或多或少都会知道一些。C、C++、Python和Java一样,它们是通用编程语言,而JavaScript和PHP算是web环境的专用编程语言。但事实上,有许多种编程语言。如果想入门编程,学习的编程语言也有很多。编程入门先学什么?随着计算机的普及,越来越多的朋友开始走上自学编程的道路。那么,作为初学者,学习编程要如何入门?编程入门先学什么?一、先了解什么是编程如果你想学习一门新知识,你应该首先了解这门知识。通过内容可以做些什么?我们可以用什么样

    2022年6月15日
  • html css制作404页面,一款纯css3实现的漂亮的404页面

    html css制作404页面,一款纯css3实现的漂亮的404页面实现的代码。html代码:404ERRORLost?MaybeIcanhelp.required/>SearchMySuggestions.HomePortfoliocss3代码:body{background-color:#0A7189;color:#fff;font:100%”Lato”,sans-serif;font-size:1.8r…

    2022年7月27日
  • linux shell 字符串截取_shell截取最后一个字符

    linux shell 字符串截取_shell截取最后一个字符因最近工作中,用到shell脚本,刚开始感觉难度比较大,但在查阅资料后,感觉也没啥难度;后续整理工作中遇到的脚本知识点;现将遇到的问题,整理如下:遇到问题:需要根据关键字,截取其定义的内容;比如截图宏定义的值,或者截取某行中最后一列数据;如下为查阅网络资料后,整理针对该问题,整理字符串截取操作如下:一、字符串截取:1.如题想提取文本中在[]之前的字符,字符与[]之间有空格;比如文本:    TF…

    2022年9月1日
  • 如何给女朋友做个树莓派复古相机?[通俗易懂]

    如何给女朋友做个树莓派复古相机?[通俗易懂]本文转载自程序员极客实验室手机拍照不够爽,带个单反又太重?试试做个树莓派复古相机,还能自己编写处理算法的那种——成本不到700元。没错,颜值很高,拍出来的照片也能打:你也可以快速上手做一个。如何制作一个树莓派复古相机目前,这部相机的代码、硬件清单、STL文件(用于3D打印)和电路图都已经开源。首先是硬件部分。这部复古相机的硬件清单如下:树莓派ZeroW(搭配microSD卡)、树莓派高清镜头模组、16mm1000万像素长焦镜头、2.2英寸TFT显

    2022年5月27日
  • nextline函数_Java 中nextLine()方法没有执行直接跳过解决办法[通俗易懂]

    nextline函数_Java 中nextLine()方法没有执行直接跳过解决办法[通俗易懂]使用Java的Scanner类nextLne()方法从显示器输入数据时,nextInt()后面的nextLine()直接跳过没有执行;截图:第三个输入直接跳过通过上网的查找我终于发现了问题出在哪里:原来nextLine()函数获取的是一整行的内容其中也包括了(\n)也就是换行符而nextInt()函数获取的仅仅是一个值不包含(\n),那么nextInt()后面的nextLine()读取一行,就把(…

    2022年5月3日
  • 巧用es6数组方法,求两数组的差集!

    巧用es6数组方法,求两数组的差集!复制代码从arr1中。根据arr2中所有的项,排除过滤掉arr2中的项。letarr1=[{id:1,num:50,text:’1111111111′},{id:2,num:100,text:’222222222′},{…

    2022年5月16日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号