次の完全な配列の次の順列
タイトル説明
実装関数nextpermutation(next permutation):順列内の数値を、辞書式順序で次に大きい順列に再配置します。順列の番号を辞書式順序で次に大きい順列に並べ替えます。
そのような配置がない場合は、辞書式順序が最小になるように配置します(昇順)。
この問題を解決するには、その場のアルゴリズムが必要です。追加のメモリスペースを申請することはできません。
次の有機グループのサンプル、左側は入力データです。 、右が出力答えである
1,2,3→1,3,2
3,2,1 1,2,3→
1,1,5→1,5,1
次の順列を実装し
ます。これは、数字を字句的に次に大きい数字の順列に再配置します。
そのような配置が不可能な場合は、可能な限り低い順序として再配置する必要があります(つまり、昇順で並べ替える必要があります)。
交換はインプレースで行う必要があり、余分なメモリを割り当てないでください。
下記は用例です。入力は左側の列にあり、対応する出力は右側の列にあります。
1,2,3→1,3,2
3,2,1 1,2,3→
1,1,5→1,5,1
問題解決のアイデア
- アイデア1:アルゴリズムヘッダーファイルの下のnext_permutation関数を使用して、シーケンスを次の完全な順列に再配置します。
- if判定を追加する必要があることに注意してください。next_permutation関数は、最後の完全な順列に達するとfalseを返します。このとき、タイトルでは、配列が最小の辞書式順序である必要があるため、並べ替えで並べ替えます。
class Solution {
public:
void nextPermutation(vector<int> &num) {
if(num.size() == 0) return ;
//如果存在下一个全排列,则返回true,否则返回false
if(next_permutation(num.begin(), num.end())) {
} else {
sort(num.begin(), num.end());
}
}
};
- アイデア2:後ろから前に見つける昇順ソート最後のポイントの添え字、ポイントの前と後の最初の要素を交換します以上この要素の番号、次に次の部分を昇順で並べ替えます
- 例:1 2 3 7 6 5 1
- 最後のポイントのインデックスを後ろから前に昇順で見つけます
- そのようなポイントがない場合は、配列全体が減少し、最大の完全な順列に達していることを証明するため、配列全体を直接反転できます。
- 上記の例の7のように、そのような点がある場合は、後ろから前に3より大きい最初の数字を探します。この例では5です。
- 5と3の位置を入れ替え、配列の次の部分を昇順で配置して結果を取得します。
class Solution {
public:
void nextPermutation(vector<int> &num) {
int n = num.size();
if(n <= 1) return ;
//标记从后往前递增排序最后一个点的下标
int index(n - 1);
//跳出循环说明是num[index] > num[index - 1],即严格递增
while(index > 0 && num[index] <= num[index - 1]) index --;
if(index == 0) {
//如果不存在这样的点
reverse(num.begin(), num.end());
} else {
//如果存在这样的点
//标记第一个大于这个点前一个元素的数
int k(n - 1);
//跳出循环说明是num[k] > num[index - 1],即严格大于
while(num[k] <= num[index - 1]) k --;
swap(num[k], num[index - 1]);
sort(num.begin() + index, num.end());
}
}
};