对于给定的序列 A={a 0​ ,a 1​ ,...,a n−1​ },按字典顺序打印前一个排列和下一个排列。

今天做oj题,有一道是求字典序法的前一个排列和下一个排列

在网络上查了很久,也没找到怎么求前一个排列。。。。

排列

对于给定的序列 A={a0​,a1​,...,an−1​},按字典顺序打印前一个排列和下一个排列。

输入

以下格式给出了一个序列。

n
a0​a1​...an−1​

输出

分别在第一行、第二行和第三行打印前一个排列、给定的序列和下一个排列。用空格字符分隔相邻元素。请注意,如果没有排列,则在相应行中不打印任何内容。

约束

  • 1≤n≤9
  • ai​ 由 1,2,...,n组成

示例输入 1

3
2 1 3

示例输出 1

1 3 2
2 1 3
2 3 1

示例输入 2

3
3 2 1

示例输出 2

3 1 2
3 2 1

唉 算了 自己动手丰衣足食!

众所周知

字典排序算法四步法:

字典排序:
第一步:从右至左找第一个左邻小于右邻的数,记下位置i,值list[a]
第二部:从右边往左找第一个右边大于list[a]的第一个值,记下位置j,值list[b] 
第三步:交换list[a]和list[b]的值
第四步:将i以后的元素重新按从小到大的顺序排列


举例:125643的下一个字典序列
第一步:右边值大于左边的3<4,4<6,6>5,则i=2,list[a]=5 
第二步:从右往左找出第一个右边大于list[a]=5的值,找到6>5,j=3;list[b]=6;
第三步:交换list[a]和list[b]的值,序列125643->126543 
第四步:将位置2以后的元素重新排序,126543->126345;
结束: 126345即125643的下一个序列 

那我把他反过来,不就是前一排序了吗!

字典上一个排序:
第一步:从右至左找第一个左邻大于右邻的数,记下位置i,值list[a]
第二部:从右边往左找第一个右边小于list[a]的第一个值,记下位置j,值list[b] 
第三步:交换list[a]和list[b]的值
第四步:将i以后的元素重新按从大到小的顺序排列

最后一提交,哦,完美!

#include<iostream>
#include<algorithm>
using namespace std;
//求下一排序
int dir(int arr[], int n)
{
	int num1 = -1,num2=0;
	//1、从原排列中,从右至左,找到第一个左邻小于右邻的字符,记左邻位置为 a。
	for (int i = n - 1; i >= 0; i--)
	{
		if (arr[i - 1] < arr[i])
		{
			num1 = i - 1;
			break;
		}
	}
	//2、重新从右至左,找到第一个比 list[a] 大的字符,记为位置为 b。
 	for (int i = n - 1; i >= 0; i--)
	{
		if (arr[i] >arr[num1])
		{
			num2 = i;
			break;
		}
	}
	if (num1 == -1)
		return 0;
	//3、交换 a 和 b 两个位置的值。
	int temp = arr[num1];
	arr[num1] = arr[num2];
	arr[num2] = temp;
	//4、将 a 后面的数,由小到大排列。
	sort(arr + num1+1, arr + n);

}
//求上一排序
int dir_1(int arr[], int n)
{
	int num1 = -1, num2 = 0;
	//1、从原排列中,从右至左,找到第一个左邻大 于右邻的字符,记左邻位置为 a。
	for (int i = n - 1; i >= 0; i--)
	{
		if (arr[i - 1] > arr[i])
		{
			num1 = i - 1;
			break;
		}
	}
	//2、重新从右至左,找到第一个比 list[a] 小的字符,记为位置为 b。
	for (int i = n - 1; i >= 0; i--)
	{
		if (arr[i] < arr[num1])
		{
			num2 = i;
			break;
		}
	}
	if (num1 == -1)
		return 0;
	//3、交换 a 和 b 两个位置的值。
	int temp = arr[num1];
	arr[num1] = arr[num2];
	arr[num2] = temp;
	//4、将 a 后面的数,由da到xiao排列。
	sort(arr + num1 + 1, arr + n,greater<int>());

}

int main()
{
	int n;
	cin >> n;
	int arr1[10],bk1[10],bk2[10];
	for (int i = 0; i < n; i++)
	{
		cin >> arr1[i];
		bk1[i] = arr1[i];
		bk2[i] = arr1[i];
	}
	int m = n;
	int count = 1;
	while (m>0)
	{
		count = count * m;
		m--;
	}
	dir_1(bk1, n);
	for (int i = 0; i < n; i++)
	{
		cout << bk1[i] << " ";
	}
	cout << endl;

	for (int i = 0; i < n; i++)
	{
		cout << bk2[i] << " ";
	}
	cout << endl;

		int num=dir(arr1, n);
		if (num != 0)
		{
			for (int i = 0; i < n; i++)
			{
				cout << arr1[i] << " ";
			}
			cout << endl;
		}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值