問題は、指定された番号シーケンスの次に大きい順列を見つけることを意味します。たとえば、指定された場合1,2,3
、123より大きい数の中で最小の番号、つまり132を見つけると、その順列は1,3,2
;になります。
アイデア:すべてが降順である場合、それ以上の順序があってはなりません。
ステップ1:昇順のペアを見つけて、12843のように大きい数字と10進数の位置を交換し、2、8を交換して18243を取得する必要がありますが、1、2を交換すると、18243より大きい21,843が得られるため、右から開始する必要があります。左に昇順で最初のペアを見つけます;
ステップ2:18243の12843より大きい最小数はそうではありません。これは、この8も、明らかに13842は12843より大きいが、18243より小さいためです。したがって、正しい2を見つけるには、2より大きい最小数が必要です。ただし、28は昇順の最初のペアであるため、次の2は降順である必要があります。したがって、右から左に2より大きい最小の数を見つけて交換するだけで、ここで13842が得られます。
ステップ3:上記の2つの手順を実行した後、13842が見つかりましたが、12843 13248 13842が大きいよりも小さいため、最小ですが、ここで13を識別したため、番号3の後ろにすべてを置きます。 3は降順であるため、最小です。これらを裏返すだけで済みます。
次の配置アルゴリズムについて詳しく説明します。アイデア+派生+ステップ、理解できない場合は負けます。
void nextPermutation(vector<int> &nums)
{
int len = nums.size();
if (len < 2)
{
return;
}
int i = len - 2, j = len - 1, k = len - 1;
//step1:从后向前找到第一对升序对
while (i >= 0 && nums[i] >= nums[j])
{
i--;
j--;
}
if (i < 0) //如果整个数组都是降序,那么设j=0,后面逆置nums[j~end]
{
j = 0;
}
else //找到升序对
{
//step2:从后向前找到第一个大于nums[i]的最小的数(肯定能找到)
while (k > i && nums[i] >= nums[k])
{
k--;
}
//交换nums[i]和nums[j]
int temp = nums[i];
nums[i] = nums[k];
nums[k] = temp;
}
//step3:逆置nums[j~end]
while (j < len - 1)
{
int temp = nums[j];
nums[j] = nums[len - 1];
nums[len - 1] = temp;
j++;
len--;
}
}