[剣指オファー] _12配列の逆ペア

タイトルの説明

配列内の2つの数値は、前の数値が後者の数値より大きい場合、これらの2つの数値は逆順のペアを形成します。配列を入力して、この配列内のペアの総数Pを逆順に検索します。そして、モジュロPの結果を1000000007に出力します。つまり、出力P%1000000007

問題解決のアイデア

ソードフィンガーオファーソリューション
この問題を見て、最初の反応はアレイ全体を順次スキャンすることです。配列がスキャンされるたびに、数値とそれに続く数値のサイズが1つずつ比較されます。次の数がそれより小さい場合、これらの2つの数は逆のペアを形成します。配列にn個の数値が含まれているとします。各数値は数値O(n)と比較する必要があるため、このアルゴリズムの時間の複雑さはO(n ^ 2)です。
統計的な逆順ペアのプロセスを分析する例として、配列{7,5,6,4}を取り上げましょう。数値をスキャンするたびに、taを後続の各数値と比較しません。それ以外の場合、時間の複雑さはO(n ^ 2)であるため、2つの隣接する数値を最初に比較することを検討できます。
ここに画像の説明を挿入
(a)長さ4の配列を長さ2の2つのサブ配列に
分解する; (b)長さ2の配列を成都の2つのサブ配列に分解する;
©長さ1のサブ配列を結合する逆順ペアをソートしてカウントする;
(d)長さ2のサブ配列を組み合わせてソートし、逆順ペアをカウントする;
上記の(a)と(b)では、最初に配列を2つのサブ長さに分解する配列し、2つのサブ配列を長さ1の2つのサブ配列に分割します。次に、隣接するサブアレイをマージしながら、逆の順序のペアの数がカウントされます。長さ1のサブアレイの最初のペア{7}と{5}では、7は5より大きいため、(7、5)は逆順のペアを形成します。同様に、長さ1のサブアレイの2番目のペア{6}と{4}にも、逆の順序のペアがあります(6、4)。これらの2つのサブ配列内で逆順のペアをすでにカウントしているため、将来の統計プロセスで統計を繰り返さないように、上の図(c)に示すように2つのペアのサブ配列をソートする必要があります。

次に、サブアレイの長さが2の2つのサブアレイ間の逆ペアをカウントします。サブアレイをマージし、リバースペアをカウントするプロセスを次の図に示します。

最初に2つのポインターを使用して2つのサブ配列の終わりを指し、2つのポインターが指す数値を毎回比較します。次の(a)と(c)に示すように、最初のサブ配列の数が2番目の配列の数より大きい場合、逆順ペアが形成され、逆順ペアの数は2番目のサブ配列の残りの数と等しくなります。見せて。図bに示すように、最初の配列の数が2番目の配列の数以下の場合、逆のペアを構成しません。比較するたびに、大きい方の数字を後ろから補助配列にコピーして、補助配列の数字(コピーと表記)が昇順でソートされるようにします。大きい方の数を補助配列にコピーした後、対応するポインターを1ビット進めてから、次の比較ラウンドを実行します。
ここに画像の説明を挿入
プロセス:最初に配列をサブ配列に分割し、最初にサブ配列内の逆順ペアの数を数え、次に2つの隣接するサブ配列間の逆順ペアの数を数えます。統計的な逆順ペアリングのプロセスでは、配列をソートすることも必要です。ソートアルゴリズムに精通している場合、このプロセスが実際にはマージソートであることを見つけるのは難しくありません。

コードの実装

class Solution {
public:
    int InversePairs(vector<int> data) {
       int length=data.size();
        if(length<=0)
            return 0;
       //vector<int> copy=new vector<int>[length];
       vector<int> copy;
       for(int i=0;i<length;i++)
           copy.push_back(data[i]);
       long long count=InversePairsCore(data,copy,0,length-1);
       //delete[]copy;
       return count%1000000007;
    }
    long long InversePairsCore(vector<int> &data,vector<int> &copy,int start,int end)
    {
       if(start==end)
          {
            copy[start]=data[start];
            return 0;
          }
       int length=(end-start)/2;
       long long left=InversePairsCore(copy,data,start,start+length);
       long long right=InversePairsCore(copy,data,start+length+1,end); 
        
       int i=start+length;
       int j=end;
       int indexcopy=end;
       long long count=0;
       while(i>=start&&j>=start+length+1)
          {
             if(data[i]>data[j])
                {
                  copy[indexcopy--]=data[i--];
                  count=count+j-start-length;          //count=count+j-(start+length+1)+1;
                }
             else
                {
                  copy[indexcopy--]=data[j--];
                }          
          }
       for(;i>=start;i--)
           copy[indexcopy--]=data[i];
       for(;j>=start+length+1;j--)
           copy[indexcopy--]=data[j];       
       return left+right+count;
    }
};
253件の元の記事を公開しました 賞賛されました41 40,000回以上の閲覧

おすすめ

転載: blog.csdn.net/liuyuchen282828/article/details/103858021