【发布时间】:2017-02-27 20:47:56
【问题描述】:
我们有一个数字 N,问题是找到最小的偶数 E,使得 E > N 并且 N 和 E 中的数字相同。 N 中的数字可能很大。
例如
- 1 -> 34722641 答案是 34724126
- 111 -> 不可能有比它更大的偶数。
- 1123 -> 输出为 1132
我通过对数字的所有数字进行排列来用蛮力完成它。我在想是否有更好的方法呢?有代码会更好。
谢谢。
【问题讨论】:
我们有一个数字 N,问题是找到最小的偶数 E,使得 E > N 并且 N 和 E 中的数字相同。 N 中的数字可能很大。
例如
我通过对数字的所有数字进行排列来用蛮力完成它。我在想是否有更好的方法呢?有代码会更好。
谢谢。
【问题讨论】:
您可以使用以下策略来寻找下一个排列:
让我们说你的number = 12344875
为了找到下一个更大的排列,你从右边开始,发现第一个数字比前一个小。
在这种情况下:number = 12344875,这是 4。
现在你从向右移动的 4 开始,找到那里最小的数字。 这是 5 -> 875。现在交换这两个数字,得到 12345874。
交换后,按升序对 5 之后的数字进行排序。 12345874 --> 12345784。 这种策略总是会导致下一个更大的排列,只有这会给出偶数和奇数。
所以为了找到下一个偶数排列,你需要稍微改变一下。 如果在最后一步中你有一个偶数,则排列该部分直到它的偶数。
否则从右边重新开始。并找到第一个偶数,它的右侧有一个更大的数字。例如数字 = 123475531。 现在交换其右侧大于 4 的最小数字。 导致以下 123575431.
从这里把偶数4放在最后,把数字放在中间 交换后的数字按升序排列,123575314 --> 123513574。
如果您有以下数字 136531。没有偶数比右边更大的数字。所以你看下一个数字, 看看右边是否有一个更大的数字(但不是第一个偶数)。这里是 136531 --> 136531 所以交换它们并将偶数放在后面,最后按升序排列。 136531 --> 156331 --> 153316 --> 151336。 p>
当数字按降序排列时(例如 97654)没有解决方案。
在进行此解释时,我意识到对于偶数,这变得更加复杂。稍后我会尝试改进答案。
我希望这很有用。 干杯
【讨论】:
找到最右边的数字i,它的右边有一个更高的数字j,其中j 不是它右边的最高偶数数字e。选择最小的j,切换i和j,将e作为最右边的数字,然后将i右侧的数字排序(升序)(不包括e)。
【讨论】:
例如 - 输入数字 - 21856521,运行第一步产生 - 21861255(奇数),因此我们再次在 21861255 上运行第 1 步产生 21861525(再次奇数),再次运行产生 21861552
PS:C++代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
string s;cin>>s;
int n = s.length();
while(true){
int idx = -1;
for(int i=n-2;i>=0;--i){
if(s[i]<s[i+1]){
idx = i;
break;
}
}
if(idx==-1){
cout<<-1<<endl;
break;
}
int swapidx = -1;
for(int i=n-1;i>=idx+1;--i){
if(s[i]>s[idx]){
swapidx = i;
break;
}
}
swap(s[idx],s[swapidx]);
//swapidx will never remain -1 bcz. we will surely find an element greater than s[idx](the right next element to idx is greater than s[idx])
sort(s.begin()+idx+1,s.end());
if((s[n-1]-'0')%2==0){
cout<<s<<endl;
break;
}
}
return 0;
}
【讨论】:
If the last digit is even then you've found the next greater even number. Otherwise, .....repeat.