タイトルの説明
配列内の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> ©,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;
}
};