首页 > 编程语言 >算法练习:排列组合之组合和

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

时间:2022-12-07 18:39:32浏览次数:41  
标签:元素 int mSrcArray 练习 算法 mDstArray IntArray 排列组合 nTarget


问题描述

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

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




 

算法练习:排列组合之组合和_代码实现

算法练习:排列组合之组合和_#include_02


系列文章说明:
1.本系列文章[算法练习],仅仅是本人学习过程的一个记录以及自我激励,没有什么说教的意思。如果能给读者带来些许知识及感悟,那是我的荣幸。
2.本系列文章是本人学习陈东锋老师《进军硅谷,程序员面试揭秘》一书而写的一些心得体会,文章大多数观点均来自此书,特此说明!
3.文章之中,难免有诸多的错误与不足,欢迎读者批评指正,谢谢.

作者:山丘儿


 

标签:元素,int,mSrcArray,练习,算法,mDstArray,IntArray,排列组合,nTarget
From: https://blog.51cto.com/u_15905375/5919885

相关文章

  • 算法练习:TopK_1
    问题描述求一维数组中最小的K个数。 方法一:排序先把数组从小到大排序,取前K个数。时间复杂度为O(nlogn)。如果数组过大,机器内存无法同时容纳整个数组,则需要使用外部排序。以......
  • Java Swing的练习感悟
    感悟心得这还是我第一次使用JavaSwing写代码呢,直接就是趣味性拉满!在相关的界面代码的基础上,在必要的位置嵌入Java代码,就可以很好的实现啦!简单的嘞!(有兴趣的各位可以选......
  • mybatis-plus雪花算法生成Id使用详解
    文章目录​​前言​​​​一、mybatis-plus官网​​​​二、雪花算法实战​​​​1.建表​​​​2.新建测试工程​​​​3.单元测试​​​​三、实现分析​​​​四、为什么......
  • mybatis-plus雪花算法增强:idworker
    文章目录​​前言​​​​一、官网​​​​二、默认实现的弊端​​​​三、mybatis-plus中datacenterId和workerId的默认生成规则​​​​四、idworker介绍​​​​五、idwo......
  • 算法练习:两指针之三数之和为0
    问题描述给出一个整型数组,找出所有三个元素的组合,其组合之和等于0。要求在结果集里不含有重复的组合。举例:输入{-2, 1, -1, 2, 1}输出{-2, 1, 1 } 问题分析最容易想到的是......
  • 第七章练习题
    组卷一软件的六大质量特性包括:功能性可靠性可用性效率可维护性可移植性软件可靠性是指在指定的条件下使用时,软件产品维持规定的性能级别的能力,......
  • 第六章练习题
    16、软件验收测试的合格通过准则是(ABCD)。你的答案A软件需求分析说明书中定义的所有功能已全部实现,性能指标全部达到要求。√正确B所有测试项没有残余一级、二级和三级......
  • c++练习272题:金币
    *272题原题传送门:http://oj.tfls.net/p/272题解:(遍历,60分)#include<bits/stdc++.h>usingnamespacestd;longlongallday;//总天数longlongpas;//已经过去longlongmo......
  • 算法练习:两数之和
    题目:给定一个整型数组,是否能找出两个数使其和为指定的某个值?注:整型数组中不存在相同的数。一、解题方法1、暴力解法(时间复杂度O(n^2) )这是最容易想到的一种方法,即使用两......
  • 操作系统:银行家算法(避免死锁)
    算法介绍:程序实现:/*****************************************************程序:银行家算法实现作者:小单时间:2013年11月5日***************************......