当前位置:首页 > > 充电吧
[导读]n选m排列是一个经典算法题,如果m = n则称为全排列。 n选m排列问题的递归算法逻辑为: 1,将m个数的排列分为两部分:一部分为包含某个数k(1

n选m排列是一个经典算法题,如果m = n则称为全排列。

n选m排列问题的递归算法逻辑为:

1,将m个数的排列分为两部分:一部分为包含某个数k(1 <= k <= n)的m排列,一部分为不包含k的m排列;

2,对于包含k的排列,又可以分为两部分:一部分为包含某个数s(k < s <= n)的m-1排列,一部分为不包含s的m-1排列;

3,对于2步所得m-1排列,将k插入到每一个排列中的m个位置可以得到m个新的m排列;

4,同步骤2,对于不包含k的排列可以进行类似的操作,最终将得到所有的n个元素的m排列。


递归算法的伪代码:



Begin:
input m, n;
if m is bigger than n, then set m = n;
if m is smaller than or equal to 0, then return;
if n is smaller than or equal to 0, then return;

PartA: get m permutation contains 1;
PartB: get m permutation not contains 1;

collect two permutations;

End;

PartA:
input k, m, n;
if m is equal to 1, then return 1 permutation only k;

PartA: get m-1 permutation contains k+1;

if m is smaller than (n - k + 1), then:
PartB: get m-1 permutation not contains k+1;

collect two permutation sets in one set;

foreach m-1 permutation, insert k to m different positions in this permutation, then get m permutation sets;

 End;

PartB:
input k, m, n
if m is equal to 1, then return (n-k+1) ones 1 permutation, each 1 permutation only contains k ~ n one element;

PartA: get m permutation contains k;
if m is smaller than (n - k + 1), then:
PartB: get m permutation not contains k;

collect two m permutation;

End;


C++代码实现:


#include 
#include 
#include 

using namespace std;


void FullPremutationPartA(int firstNo, int numPremu, int numCount, vector> &vec);

void FullPremutationPartB(int secNo, int numPremu, int numCount, vector> &vec);

void FullPremutation(int numPremu, int numCount, vector> &vec);

int main()
{
	int numPremu,
		numCount;
	vector> vec;

	cout << "Input number of Premutation: ";
	cin >> numPremu;
	cout << "Input number of count: ";
	cin >> numCount;


	FullPremutation(numPremu, numCount, vec);

	int vecSize = vec.size();
	//for (int vecIndex = 0; vecIndex < vecSize; vecIndex++)
	//{
	//	int termSize = vec[vecIndex].size();
	//	for (int tIndex = 0; tIndex < termSize; tIndex++)
	//	{
	//		cout << vec[vecIndex][tIndex] << "t";
	//	}

	//	cout << endl;
	//}
	cout << "count = " << vecSize << endl;

	return 0;
}




void FullPremutation(int numPremu, int numCount, vector> &vec)
{
	if ((numPremu <= 0) || (numCount <= 0))
		return;

	if (1 == numPremu)
	{
		for (int premuIndex = 1; premuIndex <= numCount; premuIndex++)
		{
			vector premuvec;
			premuvec.push_back(premuIndex);
			vec.push_back(premuvec);
		}

		return;
	}

	if (1 == numCount)
	{
		vector premuvec;
		premuvec.push_back(numCount);
		vec.push_back(premuvec);
		return;
	}

	if (numPremu > numCount)
	{
		FullPremutation(numCount, numCount, vec);
		return;
	}

	vector> PartAVector;
	FullPremutationPartA(1, numPremu, numCount, PartAVector);
	vec.insert(vec.end(), PartAVector.begin(), PartAVector.end());

	if (numPremu < numCount)
	{
		vector> PartBVector;
		FullPremutationPartB(2, numPremu, numCount, PartBVector);
		vec.insert(vec.end(), PartBVector.begin(), PartBVector.end());
	}

	return;
}


/****************************************************************
 * Function that process Premutation from firstNo to numCount
 * with count number of numPremu containing firstNo.
*****************************************************************/
void FullPremutationPartA(int firstNo, int numPremu, int numCount, vector> &vec)
{
	if (firstNo > numCount)
		return;


	if ((1 == numPremu) || (firstNo == numCount))
	{
		vector premuVec;
		premuVec.push_back(firstNo);
		vec.push_back(premuVec);
		return;
	}


	vector> PartAVector;
	FullPremutationPartA(firstNo + 1, numPremu - 1, numCount, PartAVector);

	vector> nunFullVector;
	nunFullVector.insert(nunFullVector.end(), PartAVector.begin(), PartAVector.end());
	
	if (numPremu < (numCount - firstNo + 1))
	{
		vector> PartBVector;
		FullPremutationPartB(firstNo + 2, numPremu - 1, numCount, PartBVector);
	
		nunFullVector.insert(nunFullVector.end(), PartBVector.begin(), PartBVector.end());
	}
		
	
	int fullSize = nunFullVector.size();
	int termSize = nunFullVector[0].size();
	vec.resize(fullSize * (termSize + 1));
	int vecIndex = 0;
	
	for (int preIndex = 0; preIndex < fullSize; preIndex++)
	{
		vector tmpVector;
		tmpVector.resize(termSize + 1);
		copy(nunFullVector[preIndex].begin(), nunFullVector[preIndex].end(), tmpVector.begin());
		tmpVector[termSize] = firstNo;
		vec[vecIndex].assign(tmpVector.begin(), tmpVector.end());
		vecIndex++;
		
		for (int termIndex = termSize; termIndex > 0 ; termIndex--)
		{
			tmpVector[termIndex] = tmpVector[termIndex - 1];
			tmpVector[termIndex - 1] = firstNo;

			vec[vecIndex].assign(tmpVector.begin(), tmpVector.end());
			vecIndex++;
		}
	}

	return;
}

/****************************************************************
 * Function that process Premutation from SecNo to numCount
 * with count number of numPremu
*****************************************************************/
void FullPremutationPartB(int secNo, int numPremu, int numCount, vector> &vec)
{
	if (secNo > numCount)
		return;

	if (1 == numPremu)
	{
		for (int premuIndex = secNo; premuIndex <= numCount; premuIndex++)
		{
			vector premuVec;
			premuVec.push_back(premuIndex);
			vec.push_back(premuVec);			
		}

		return;
	}

	if (secNo == numCount)
	{
		vector premuVec;
		premuVec.push_back(secNo);
		vec.push_back(premuVec);
		return;
	}	

	
	vector> PartAVector;
	FullPremutationPartA(secNo, numPremu, numCount, PartAVector);
	vec.insert(vec.end(), PartAVector.begin(), PartAVector.end());

	if (numPremu < (numCount - secNo + 1))
	{
		vector> PartBVector;
		FullPremutationPartB(secNo + 1, numPremu, numCount, PartBVector);
		vec.insert(vec.end(), PartBVector.begin(), PartBVector.end());
	}

	return;
}

我的实现对于n较小的时候,效率问题体现不出来,当n比较大的时候,效率特别慢,有更好的方法的朋友可以提点一些。

在实现的过程中,发现设计很重要,刚开始没有进行详细的设计,仅仅根据一点思路去实现,走了很多弯路,也花了很多的时间。所以算法设计一定要设计清晰,在实现中才能有的放矢的完善细节。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭