私は現在、マージソートを使用して反転演習を数えることに取り組んでいます。私が直面している問題は、小規模または中規模の配列がある場合、結果は完全に問題ありませんが、非常に大きなテストケース (100,000 個の整数の配列) を使用すると、正しい数の反転が得られないことです。なぜそれが起こっているのか、私には手がかりがありません。これが私のコードです:
static int [] helper;
static long count=0;
static Integer [] arr3;
private static void mergeSortMethod(Integer[] arr3) {
int head=0;
int tail=arr3.length-1;
int mid=tail+((head-tail)/2);
sort(arr3,head,tail);
}
private static void sort(Integer[] arr3, int low, int high) {
if (high<=low){
return;
}
int mid=low+ ((high-low)/2);
sort(arr3,low,mid);
sort(arr3,mid+1,high);
merge3CountInvs(arr3,low,mid,high);
}
private static void merge3CountInvs(Integer[] arr3, int low, int mid, int high) {
int i=low;
int j=mid+1;
int k=low;
//to get size of first half of array
int nArr1Elems=(mid-low)+1;
for (int m=low;m<=high;m++){
helper[m]=arr3[m];
}
while(i < mid+1 && j < high+1){// neither array empty
if( helper[i] < helper[j] ){
arr3[k++] = helper[i++];
}
else if ( helper[j] < helper[i] ){
arr3[k++] = helper[j++];
int numOFElements=nArr1Elems-i;
count=count+(nArr1Elems-i);
}
}
while(i < mid+1){ // arrayB is empty,
arr3[k++] = helper[i++];
}
while(j < high+1){ // arrayA is empty,
arr3[k++] = helper[j++];
}
}
非常に大きな入力を使用しない場合、私のソリューションは正しい答えを返しますが、取得した反転の数である 100,000 の整数のテスト ケースを使用した場合:
私の実装から: -30588581433
正解:2407905288
何か案は?あらゆる種類の助けをいただければ幸いです。ありがとうございました。
編集:整数オーバーフローのケースについての回答で述べたように、オーバーフローを引き起こす変数「カウント」が「ロング」として初期化されるため、理解するのに苦労しています。この場合、オーバーフローはありません。私のコードで整数オーバーフローを引き起こす他の変数は考えられません。どうもありがとう。
アップデート:
整数オーバーフローに関連する問題はありませんでしたが、回答に感謝しますが、Reddy の回答は私を正しい方向に向けてくれたので、もう一度感謝します。私のアルゴリズムの唯一の間違いは次のとおりです。
int nArr1Elems=(mid-low)+1;
count=count+(nArr1Elems-i);
あるべきとき:
count=count+(mid-i+1);
並べ替え後にインデックスが変更されるため、最初はサブルーチンが呼び出されたときではなく、並べ替えの「後」に配列の左側に残っている要素から減算する必要があるためです。他の誰かが私のような問題に遭遇した場合に備えて、更新されたコードを書いています。
static int [] helper;
static long count=0;
static Integer [] arr3;
private static void mergeSortMethod(Integer[] arr3) {
int head=0;
int tail=arr3.length-1;
int mid=tail+((head-tail)/2);
sort(arr3,head,tail);
}
private static void sort(Integer[] arr3, int low, int high) {
if (high<=low){
return;
}
int mid=low+ ((high-low)/2);
sort(arr3,low,mid);
sort(arr3,mid+1,high);
merge3CountInvs(arr3,low,mid,high);
}
private static void merge3CountInvs(Integer[] arr3, int low, int mid, int high) {
int i=low;
int j=mid+1;
int k=low;
for (int m=low;m<=high;m++){
helper[m]=arr3[m];
}
while(i < mid+1 && j < high+1){// neither array empty
if( helper[i] < helper[j] ){
arr3[k++] = helper[i++];
}
else if ( helper[j] < helper[i] ){
arr3[k++] = helper[j++];
//to increment count with total number of elements left in arrayA after sorting
count=count+(mid-i+1);
}
}
while(i < mid+1){ // arrayB is empty,
arr3[k++] = helper[i++];
}
while(j < high+1){ // arrayA is empty,
arr3[k++] = helper[j++];
}
}