C++:全排列函数next_permutation()和prev_permutation()


前言

字节三面,考了leetcode556题,复盘发现了两个超好用的函数,C++STL中的全排列函数为两个:next_permutation和prev_permutation
其中:next_permutation实现升序,而prev_permutation实现降序


一、next_permutation()用法

next_permutation()函数的返回类型是bool类型。

即:如果有一个更高的排列,它重新排列元素并返回true;如果这是不可能的(因为它已经在最大可能的排列),它按升序排列重新元素,并返回false

使用:

next_permutation,重新排列范围内的元素[第一,最后一个)返回按照字典序排列的下一个值较大的组合

next_permutation()函数功能是输出所有比当前排列大的排列,顺序是从小到大。

算法描述:

1、从尾部开始往前寻找两个相邻的元素

第1个元素i,第2个元素j(从前往后数的),且i<j

2、再从尾往前找第一个大于i的元素k。将i、k对调

3、[j,last)范围的元素置逆(颠倒排列)

简单使用

例子1

#include <iostream>
#include <algorithm>
using namespace std;

int main() {

	char data1[] = "abcd";
	char data2[] = "bcad";
	char data3[] = "abcc";
	char data4[] = "1234";
	char data5[] = "3124";
	char data6[] = "1233";

	do {
		puts(data1);
	} while (next_permutation(data1, data1 + 4));
	cout << endl;

	do {
		puts(data2);
	} while (next_permutation(data2, data2 + 4));
	cout << endl;

	do {
		puts(data3);
	} while (next_permutation(data3, data3 + 4));
	cout << endl;

	do {
		puts(data4);
	} while (next_permutation(data4, data4 + 4));
	cout << endl;

	do {
		puts(data5);
	} while (next_permutation(data5, data5 + 4));
	cout << endl;

	do {
		puts(data6);
	} while (next_permutation(data6, data6 + 4));
	cout << endl;


	system("pause");
	return 0;
}
  • 结果:
abcd
abdc
acbd
acdb
adbc
adcb
bacd
badc
bcad
bcda
bdac
bdca
cabd
cadb
cbad
cbda
cdab
cdba
dabc
dacb
dbac
dbca
dcab
dcba

bcad
bcda
bdac
bdca
cabd
cadb
cbad
cbda
cdab
cdba
dabc
dacb
dbac
dbca
dcab
dcba

abcc
acbc
accb
bacc
bcac
bcca
cabc
cacb
cbac
cbca
ccab
ccba

1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321

3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321

1233
1323
1332
2133
2313
2331
3123
3132
3213
3231
3312
3321

第m个最小的数字序列

  • 题目:给定一个从1到N的序列,我们定义1,2,3…N-1,N,是所有可以由1到N组成的序列中最小的序列(每个数字只能使用一次)。 因此,很容易看到第二个最小的序列是1,2,3…N,N-1。 现在我给你两个数字N和M。你应该告诉我第M个最小的序列,它由1到N组成。
  • 输入:每个测试用例均包含两个数字N和M(1 <= N <= 1000,1 <= M <= 10000)。 您可能会假设总是有一个序列满足BEelzebub的需求。 输入在文件末尾终止。
    6 4
    11 8
  • 输出:对于每个测试用例,您只需输出满足BEelzebub要求的序列即可。 输出序列时,应在两个数字之间打印一个空格,但不要在最后一个数字之后输出任何空格。
    1 2 3 5 6 4
    1 2 3 4 5 6 7 9 8 11 10
#include<cstdio>    
#include<algorithm>
#include<vector>
#include <iostream>
using namespace std;
int main()
{
	int n, m;
	while (cin>>n>>m)
	{
		vector<int> a(n,0);
		for (int i = 0; i < n; i++)
			a[i] = i + 1;
		int num = 0;
		do
		{
			num++;
			if (num == m)
			{
				for (int i = 0; i < n; i++)
				{
					if (i == 0)
					{
						cout << a[i];

					}
					else
						cout << " " << a[i];
				}
				cout << endl;
				break;
			}
		} while (next_permutation(a.begin(), a.end()));
	}
	system("pause");
	return 0;
}

在这里插入图片描述

自定义排序

大小写字母排序

  • 题目:您将要编写一个程序,该程序必须根据给定的字母集生成所有可能的单词。
    示例:给定单词“ abc”,您的程序应-通过探索三个字母的所有不同组合-输出单词“ abc”,“ acb”,“ bac”,“ bca”,“ cab”和“ cba”。
    在从输入文件中提取的单词中,某些字母可能会出现多次。 对于给定的单词,您的程序不应多次产生相同的单词,并且单词应按字母升序输出。
  • 输入:输入由几个词组成。 第一行包含一个数字,给出要跟随的单词数。 接下来的每一行包含一个单词。 单词由A到Z的大写或小写字母组成。大写和小写字母应被视为不同。 每个单词的长度小于13。
    Sample Input:
    3
    aAb
    abc
    acba
  • 输出:对于输入中的每个单词,输出应包含可以使用给定单词的字母生成的所有不同单词。 由相同输入单词生成的单词应按字母升序输出。 大写字母位于相应的小写字母之前。
    Sample Output
    Aab
    Aba
    aAb
    abA
    bAa
    baA
    abc
    acb
    bac
    bca
    cab
    cba
    aabc
    aacb
    abac
    abca
    acab
    acba
    baac
    baca
    bcaa
    caab
    caba
    cbaa
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>

using namespace std;

int cmp(char a, char b)            //自定义函数,实现字母大写排在小写前面的功能
{
	if (tolower(a) != tolower(b)) //tolower是将大写转化为小写,A-Z 65-90       a-z 97-122
		return tolower(a) < tolower(b);
	else
		return a < b;
}
int main()
{
	int n;
	cin >> n;
	string s="";
	while (n--)
	{
		cin >> s;
		int len = s.size();
		sort(s.begin(), s.end(), cmp);
		do
		{
			cout << s << endl;
		} while (next_permutation(s.begin(), s.end(), cmp)); //自定义函数的使用
	}
	system("pause");
	return 0;
}

在这里插入图片描述

二、prev_permutation()用法

prev_permutation()函数功能是输出所有比当前排列小的排列,顺序是从大到小。

  • 例子:
#include <iostream>
#include <algorithm>
using namespace std;

int main() {

	char data1[] = "dbca";
	char data2[] = "bcad";
	char data3[] = "dbcc";
	char data4[] = "4321";
	char data5[] = "3124";
	char data6[] = "3312";

	do {
		puts(data1);
	} while (prev_permutation(data1, data1 + 4));
	cout << endl;

	do {
		puts(data2);
	} while (prev_permutation(data2, data2 + 4));
	cout << endl;

	do {
		puts(data3);
	} while (prev_permutation(data3, data3 + 4));
	cout << endl;

	do {
		puts(data4);
	} while (prev_permutation(data4, data4 + 4));
	cout << endl;

	do {
		puts(data5);
	} while (prev_permutation(data5, data5 + 4));
	cout << endl;

	do {
		puts(data6);
	} while (prev_permutation(data6, data6 + 4));
	cout << endl;


	system("pause");
	return 0;
}
  • 结果:
dbca
dbac
dacb
dabc
cdba
cdab
cbda
cbad
cadb
cabd
bdca
bdac
bcda
bcad
badc
bacd
adcb
adbc
acdb
acbd
abdc
abcd

bcad
badc
bacd
adcb
adbc
acdb
acbd
abdc
abcd

dbcc
cdcb
cdbc
ccdb
ccbd
cbdc
cbcd
bdcc
bcdc
bccd

4321
4312
4231
4213
4132
4123
3421
3412
3241
3214
3142
3124
2431
2413
2341
2314
2143
2134
1432
1423
1342
1324
1243
1234

3124
2431
2413
2341
2314
2143
2134
1432
1423
1342
1324
1243
1234

3312
3231
3213
3132
3123
2331
2313
2133
1332
1323
1233

三、STL next_permutation和prev_permutation 算法原理

算法原理


参考

参考文章1
参考文章2

我不会,我可以学!

  • 8
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值