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

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

时间:2022-12-07 18:39:56浏览次数:47  
标签:bUseFlag mDstArrayTemp mSrcArray 之全 back gResultSet 算法 IntArray 排列组合


问题描述

输入一个不含相同数字的序列,输出所有可能的排列。

 

问题分析

与之前的“求解子集合”类似,使用递归方法:典型的在for循环内调用递归函数。不同的是,必须等到所有的数字均在集合里才能输出。为了记录每个数字的使用情况,还需一个辅助数组记录每个数字的使用情况。详见代码部分的FullPermutation函数。

 

 

扩展问题

如果数列中含有重复的数字,并且输出的结果不含重复组合,那么怎么处理?比如,输入{1,1,2},输出{1,1,2}, {1,2,2}, {2, 1, 1}。我们在挑选数字的时候,除了考虑当前使用情况外,还需要判断前一个相同元素的使用情况。如果前一个相同元素还未被使用,那么当前元素也不应该被使用,确保输出是唯一的。详见代码部分的FullPermutationEx函数。

 

实现代码

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

using namespace std;

typedef vector<int> IntArray;
typedef vector<bool> BoolArray;
typedef vector<vector<int>> ResultSet;

ResultSet gResultSet; //结果集合


//递归求解全排列(源序列中不含有相同的元素)
void FullPermutation( const IntArray& mSrcArray, IntArray& mDstArrayTemp, BoolArray& bUseFlag )
{
if ( mDstArrayTemp.size() >= mSrcArray.size() )
{
//求得一个结果
gResultSet.push_back( mDstArrayTemp );
}
else
{
for( int i = 0; i < mSrcArray.size(); ++i )
{
//已经被使用
if ( bUseFlag[i] ) continue;

mDstArrayTemp.push_back( mSrcArray[i] );
bUseFlag[i] = true;

//递归处理
FullPermutation( mSrcArray, mDstArrayTemp, bUseFlag );


//重置,即回溯
mDstArrayTemp.pop_back();
bUseFlag[i] = false;
}
}
}


//递归求解全排列(源序列中含有相同的元素)
void FullPermutationEx( const IntArray& mSrcArray, IntArray& mDstArrayTemp, BoolArray& bUseFlag )
{
if ( mDstArrayTemp.size() >= mSrcArray.size() )
{
//求得一个结果
gResultSet.push_back( mDstArrayTemp );
}
else
{
for( int i = 0; i < mSrcArray.size(); ++i )
{
// //已经被使用
// if ( bUseFlag[i] ) continue;

//除了考虑当前使得情况外,还需判断是否为重复元素的第一个
//如果前一个相同元素还未被使用,那么当前元素也不应该被使用,确保输出唯一
if( bUseFlag[i] || ( i > 0 && !bUseFlag[i-1] && mSrcArray[i] == mSrcArray[i-1]) )
continue;

mDstArrayTemp.push_back( mSrcArray[i] );
bUseFlag[i] = true;

//递归处理
FullPermutationEx( mSrcArray, mDstArrayTemp, bUseFlag );


//重置,即回溯
mDstArrayTemp.pop_back();
bUseFlag[i] = false;
}
}
}

//输出结果集
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;
BoolArray bUseFlag;

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

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

mDstArrayTemp.clear();
gResultSet.clear();

//递归求解全排列
//FullPermutation( mSrcArray, mDstArrayTemp, bUseFlag );
FullPermutationEx( mSrcArray, mDstArrayTemp, bUseFlag );

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



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

作者:山丘儿



 

标签:bUseFlag,mDstArrayTemp,mSrcArray,之全,back,gResultSet,算法,IntArray,排列组合
From: https://blog.51cto.com/u_15905375/5919884

相关文章

  • 算法练习:排列组合之组合和
    问题描述给出一组不同的正整数序列和一个目标值,求出所有可能的组合,使得组合里所有元素和为目标值。要求:1)每个组合里的元素按照升序排列。2)输出组合里不含有重复的组合。3)输......
  • 算法练习:TopK_1
    问题描述求一维数组中最小的K个数。 方法一:排序先把数组从小到大排序,取前K个数。时间复杂度为O(nlogn)。如果数组过大,机器内存无法同时容纳整个数组,则需要使用外部排序。以......
  • 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 } 问题分析最容易想到的是......
  • 算法练习:两数之和
    题目:给定一个整型数组,是否能找出两个数使其和为指定的某个值?注:整型数组中不存在相同的数。一、解题方法1、暴力解法(时间复杂度O(n^2) )这是最容易想到的一种方法,即使用两......
  • 操作系统:银行家算法(避免死锁)
    算法介绍:程序实现:/*****************************************************程序:银行家算法实现作者:小单时间:2013年11月5日***************************......
  • KMP算法详解-字符串匹配
    1.什么是KMP是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP2.KMP的用处KMP主要用于字符串匹配。KMP的主要思想是当出现字符串不匹......
  • 算法练习:两指针之有序数组去重
    问题描述给出一个有序数组,就地移除重复元素,保持每个元素只出现一次,并返回新数组的长度。 问题分析这个比较简单,直接使用两个指针,一个在前,一个在后,扫描一遍数组即可。时间复......
  • 算法练习:两指针之三色排序
    问题描述输入一个整型数组,每个元素在0~2之间,其中0,1,2分别代表红、白、蓝。现要求对数组进行排序,相同颜色的在一起,而且按红白蓝顺序先后排列。要求时间复杂度为O(n)。 问题分......