每日一题(?)——下一排列

真的猛士,敢于直面惨淡的人生,敢于正视淋漓的鲜血。这是怎样的哀痛者和幸福者?然而造化又常常为庸人设计,以时间的流驶,来洗涤旧迹,仅使留下淡红的血色和微漠的悲哀。在这淡红的血色和微漠的悲哀中,又给人暂得偷生,维持着这似人非人的世界。我不知道这样的世界何时是一个尽头!
我们还在这样的世上活着;我也早觉得有写一点东西的必要了。离数期末也已不足两个月,数据结构可能真的要凉了罢,我正有写一点东西的必要了。本来想在自己公众号上更的,结果被其他人说不可能有人看,还会有人取关。emmmm那我就只能在这更了。如果有时间就每日一题,没时间就每周一题。

下一排列

将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

样例:

1,2,3 → 1,3,2

3,2,1 → 1,2,3

1,1,5 → 1,5,1

输入

第一行是数字n(n <= 100)
接下来是n个数字。

输出

输入的n个数字的下一排列。每个数字之间用空格隔开。

样例输入

5
1 2 3 4 5

样例输出

1 2 3 5 4

思路:寻找下一排列就是找比这个数大的下一个整数。所以我们要调整这个数里面每个数的位置,而且幅度要尽可能小。我们可以从后往前找到第一个不是升序的数,即这个数比后面的数小,例如1234765321,从最后一位到7都是升序排列,而4比7小。然后我们从4开始往后找,找到比4大且相差最小的数,即5,两者调换位置,这样就得到了比原数在百万位大的下一个数,然后把后面的数从小到大排列就找到了比原数大的下一个数。

下面贴一张leetcode上官方解答动图,有助于理解:

Next Permutation

代码:

#include<iostream>
using namespace std;
int findnearest(int*arr, int size, int num)
{
	int min_index = 0;
	for (int i = 0; i < size; i++)
	{
		if ((arr[i] - num < arr[min_index] - num)&& (arr[i] - num>0))
			min_index = i;
	}
	return min_index;
}
void swap(int*a, int*b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
void sort(int *arr, int size)
{
	int temp = 0;
	for (int i = 0; i < size-1; i++)
	{
		for (int j = 0; j < size - 1 - i; j++)
			if (arr[j] > arr[j + 1])
				{
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
	}
}

int main()
{
	int num;
	cin >> num;
	int *arr = new int[num];
	for (int i = 0; i < num; i++)
	{
		cin >> arr[i];
	}
	int j = -1;
	for (int i = num - 1; i >= 1; i--)
	{
		if (arr[i - 1] < arr[i])
		{
			j = i - 1;
			break;
		}
	}
	if (j != -1)
	{
		int index = j + 1 + findnearest((arr + j + 1), num - j - 1, arr[j]);
		swap(arr[j], arr[index]);
		sort((arr + j + 1), num - j - 1);
	}
	else
	{
		sort(arr, num);
	}
	for (int i = 0; i < num; i++)
	{
		cout << arr[i] << " ";
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ZhangyunqingGC/article/details/84747600