給定一個若干整數的排列,給出按正數大小進行字典序從小到大排序後的下一個排列。c++
若是沒有下一個排列,則輸出字典序最小的序列。數組
樣例code
左邊是原始排列,右邊是對應的下一個排列。排序
1,2,3 → 1,3,2 3,2,1 → 1,2,3 1,1,5 → 1,5,1
先看一個例子:it
8, 5, 3, 7, 6, 5, 4, 1
下一個排列應該是:io
8, 5, 4, 1, 3, 5, 6, 7
看起來應該是要從後往前找,找到第一個降序的數字,由於若是一直都是升序的話,說明這一部分以及是全排列的最大狀況了。第一個比它後一個數小的數,就是須要替換爲比他大一點的那個數。在上面的例子中就是3
.class
找到3
之後,須要把它替換成一個比它大一點的數,因而再從後往前找,找到第一個比它大的數,在上面的例子中,就是4
左邊是原始排列,右邊是對應的下一個排列。next
將3
和4
交換,因爲後半部分剛纔已是最大的全排列了,因此須要翻轉一下,變成最小的全排列。co
整個過程大概以下:字典
8, 5, 3, 7, 6, 5, 4, 1
8, 5, 3, 7, 6, 5, 4, 1
8, 5, 3, 7, 6, 5, 4, 1
8, 5, 4, 7, 6, 5, 3, 1
8, 5, 4, 7, 6, 5, 3, 1
8, 5, 4, 1, 3, 5, 6, 7
考慮一些特殊狀況,若數組長度小於等於1,則下一個排列就是它自己,因此直接返回。
若數組自己就是最大的全排列,則在第一次從前日後尋找第一個比它後一個數小的數時,找到最前面也找不到,因而就不須要找第二個數了,直接將整個數組翻轉就行了。
// 下一個排列 void nextPermutation(vector<int> &nums) { if (nums.size() <= 1) return; vector<int>::iterator l = nums.end() - 2; for (; l >= nums.begin(); --l) if (*l < *(l + 1)) break; if (l >= nums.begin()) { vector<int>::iterator r = nums.end() - 1; for (; r != l; --r) if (*r > *l) break; swap(*l, *r); } reverse(l + 1, nums.end()); }