next_permutation算法(基于交换)
nextpermutation 算法
這個算法如何實現 我們要觀察對于任意的123456
對于一個任意的字符串
我們如果要找他的下一個全排列
就應該變動其數字 使得其數值增大 且是最小的增大
那么僅使用以上數字 如何才能使其變大 但變大的數字 是所有變大范圍內最小的可能 我們稱其為 最小變大
我們看 如果是 1234 下一個數 1243
再來 1243 下一個數是 1342
那么 1342 下一個數是 1423 > 1432
1432 > 2134
像4,43,432這種時候
就需要 把后面的一個數字和前面的一個數字更換
從而實現到最小變大 那么進一步地
我們發現 每次這種變化都是一個遞減序列 (如 4,43,432)
把其中最小的數字 和4前面的數字交換 得到一個新序列
因為只有這樣才能保證 我們得到新序列才是向“最小變大”
我們需要在后面的遞減序列中找到一個比遞減序列第一個元素前的
那個元素 我們姑且叫他第0號元素 我們找到一個比0號元素大的
且是最接近0號元素的數字 和 0號交換 才能實現“最小變大“
好了 那么 我們就有代碼的思路了
我們發現 任何數串 都可以看成一個后面拖著一個遞減序列的數串
無論是什么數字 后面總有一個遞減序列 有的是一個元素,有的是多個元素
如何找到他下一個排列?我們要做的是
把遞減序列前的第0元素 和遞減序列中的比0號元素大且最接近的元素
他倆交換 這樣才能實現變大 而且可以推得 遞減序列中一定存在元素比第0號元素大
為什么呢? 因為若是不這樣 0號元素就在非嚴格
遞減序列里了 所以一定遞減序列中有元素比他大
那么 交換完成后就完成任務了嗎? 還不夠
比如 1342 ?> 1432 >1423
? ? ? ? 1 ? ? ?2 ? ? 3
我們發現 還需要調整一下才能得到交換后的數串最小
如何調整? 就是要把交換后原來的遞減序列從小到大排序才能使其最小
所以我們這里就知道了 由于交換后的0號元素新位置 本來就比0號大
所以仍舊是遞減序列
那么就總結為這幾個步驟
1 找出遞減序列前的第0元素
2 找出遞減序列中大于第0元素的最接近元素
3 交換兩個元素
4 將0號元素后的序列從小到大排序
我們就得到了他的下一排列
?
模板例題:POJ-3785
題意:就是求下一個排列
?
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; char a[100]; bool Next(int s,int e){int l,j = e-1;while(j>0&&a[j]>=a[j+1])j--; //1if(j==0)return 0;//如果完全逆序 則不必交換 已經是最大可能了for(l = e;a[l]<=a[j];l--);//2swap(a[l],a[j]);//3reverse(a+j+1,a+e+1);//4return 1; } int main(){int n;scanf("%d",&n);while(n--){int num;scanf("%d %s",&num,a+1);int len = strlen(a+1);if(Next(1,len))printf("%d %s\n",num,a+1);else printf("%d BIGGEST\n",num);}return 0; }?
總結
以上是生活随笔為你收集整理的next_permutation算法(基于交换)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos 安装mysql时错误unk
- 下一篇: 标C编程笔记day04 预处理、宏定义、