问题描述
2018年清华软院推免考试(校外直博&校内硕/博)
第二题——超长整数排列(Arrange)
输入一个任意长度的数字序列,如果将数字序列的每一位看做一个单独的数字,则每个序列都可以看做是由数字0~9组成的一个排列。输出比输入序列大的最小排列,如果这样的序列不存在,则输出输入序列。
示例:
Input
123
Output
132
Explanation
"1""2""3"组成的排列从小到大有123,132,213,231,312,321,其中大于123的最小者是132
(因为是考后回忆,可能记忆有些模糊了,题干和代码都有可能有错,忘谅解)
------------------------------------------------------------
思路
由于事先不知道输入序列的长度,因此可以用std::string读取输入,记作s。
算法比较简单,从个位开始往前遍历,如果存在相邻两位(不妨记作第i位和第i+1位)使得s[i] < s[i+1],则将s[i]与s[i+1 : s.length()-1]中比s[i]大的最小者交换,再将交换后的s[i+1 : s.length()-1]升序排列即可得到比s大的排列中的最小者。算法复杂度是O(NlogN)
------------------------------------------------------------
代码
//输入一个任意长度的数字序列,如果将数字序列的每一位看做一个单独的数字,则每个序列都可以看做是由数字0~9组成的一个排列。
//输出比输入序列大的最小排列,如果这样的序列不存在,则输出输入序列。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string s;
cin >> s;
int n = s.length(), i, j, minid;
char a, minv;
for (i=n-2; i>=0; i--)
{
if (s.at(i) < s.at(i+1))
{
// 找s[i+1 : s.length()-1]中比s[i]大的最小者
minv = '9' + 10;
minid = i + 1;
a = s.at(i);
for (j = i+1; j < n; j++)
{
if (s.at(j) > a && s.at(j) < minv)
{
minv = s.at(j);
minid = j;
}
}
swap(s.at(i), s.at(minid));
sort(s.begin() + i + 1, s.end());
break;
}
}
cout << s;
return 0;
}