今日の1つの質問をLeetcode:31.next-permutation(next-permutation)

ここに写真の説明を挿入
問題は、指定された番号シーケンスの次に大きい順列を見つけることを意味します。たとえば、指定された場合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--;
    }
}

おすすめ

転載: blog.csdn.net/wyll19980812/article/details/109235586