[英]How can I return the number of pairs that do not satisfy the sorting condition from largest to smallest using merge sort?
我有一個 function public static int countBaad(int[] hs)
接受一個輸入數組,我應該找出有多少數字小於它前面的數字。
例如,
如果hs = [7,3,5,4,1]
答案將是 2,因為違反順序的對是 3 和 5 以及 3 和 4,因為 3 比它們小並且應該在它們之前。
如果hs = [8,5,6,7,2,1]
答案將是 3,因為 5 小於 6 和 7,給我們 2,並且由於 6 也小於 7,我們將得到總共 3錯誤的對
這是我當前使用合並排序方法的代碼:
public static int countBaad(int[] hs){
return mergeSort(hs, hs.length);
}
public static int mergeSort(int[] a, int n) {
if (n < 2) {
return n;
}
int mid = n / 2;
int[] l = new int[mid];
int[] r = new int[n - mid];
for (int i = 0; i < mid; i++) {
l[i] = a[i];
}
for (int i = mid; i < n; i++) {
r[i - mid] = a[i];
}
mergeSort(l, mid);
mergeSort(r, n - mid);
return merge(a, l, r, mid, n - mid);
}
public static int merge(int[] a, int[] l, int[] r, int left, int right) {
int size = 0;
int i = 0, j = 0, k = 0;
while (i < left && j < right) {
if (l[i] <= r[j]) {
a[k++] = l[i++];
size++;
}
else {
a[k++] = r[j++];
size++;
}
}
while (i < left) {
a[k++] = l[i++];
size++;
}
while (j < right) {
a[k++] = r[j++];
size++;
}
return size;
}
在我輸入 arrays 后,這段代碼給了我錯誤的 output
hs = [7,3,5,4,1]
返回 5
hs = [8,5,6,7,2,1]
返回 6
我在這里做錯了什么,有人可以糾正我嗎?
您的代碼當前正在做的是嘗試進行排序,然后簡單地返回排序數組的大小(大驚喜,給定恰當命名的size
變量)。
基本上,您按降序排序,您的規范要求結果是有多少數字小於數組中后面出現的數字。 但是,在merge
中,您實際上是在增加size
,而不管它們的值如何。
然后,您只返回最終合並的“大小”結果,而不返回其間所需的排序步驟的結果。
最后,也許房間里的大象是您正在執行(不必要的)排序作為副作用,但完全忽略了它。
長話短說,代碼過於復雜且容易出錯,無法實現其應有的功能。
這是一個簡單的雙 for 循環,可以達到預期的結果:
public static int countBaad(int[] hs){
int count = 0;
for(int i = 0; i < hs.length; i++) {
for(int j = i+1; j < hs.length; j++) {
//compare the i'th position with all subsequent positions
int current = hs[i];
int other = hs[j];
if(current < other) {
System.out.println("Found bad number pair: ("+current+","+other+")");
count++;
}
}
}
return count;
}
System.out.println(countBaad(new int[]{7,3,5,4,1}));
//prints:
//Found bad number pair: (3,5)
//Found bad number pair: (3,4)
//2
System.out.println(countBaad(new int[]{8,5,6,7,2,1}));
//prints:
//Found bad number pair: (5,6)
//Found bad number pair: (5,7)
//Found bad number pair: (6,7)
//3
這更加簡潔並且沒有副作用。
編輯:
修復 mergeSort 代碼,使用額外的 sysout 日志記錄來說明算法:
public static int mergeSort(int[] a, int n) {
if(n==1) {
//No sorting required, so the result should be 0.
return 0;
}
int mid = n / 2;
int[] l = new int[mid];
int[] r = new int[n - mid];
//'splitting the array' loops are just arraycopy, so
// should use the native implementation:
System.arraycopy(a, 0, l, 0, mid);
if(n - mid >= 0) System.arraycopy(a, mid, r, 0, n - mid);
//add the results from all merges, not just the last one
int result = 0;
result += mergeSort(l, mid);
result += mergeSort(r, n - mid);
result += merge(a, l, r); //there is no need to pass in the array lengths
return result;
}
public static int merge(int[] a, int[] l, int[] r) {
System.out.println("Merging "+Arrays.toString(l)+" and "+Arrays.toString(r));
int size = 0;
int lIdx = 0, rIdx = 0, aIdx = 0;
while (lIdx < l.length && rIdx < r.length) {
if (l[lIdx] >= r[rIdx]) {
a[aIdx++] = l[lIdx++];
//size++; //no: left was already bigger than right
}
else {
//take from the right.
//This number is bigger than all the numbers remaining on the left.
for(int tempIdx = lIdx;tempIdx<l.length;tempIdx++) {
//this loop is for illustration only
System.out.println(" Found bad pair: (" + l[tempIdx] + "," + r[rIdx] + ")");
}
size+=l.length-lIdx;
a[aIdx++] = r[rIdx++];
}
}
//while (lIdx < left) { //NOTE that you had this condition incorrectly reversed resulting in bad merge
// a[aIdx++] = l[lIdx++];
// size++; //no, no comparisons are taking place here
//}
//while (rIdx < right) { //NOTE that you had this condition incorrectly reversed, resulting in bad merge
// a[aIdx++] = r[rIdx++];
// size++; //no, no comparisons are taking place here
//}
//we can also replace the above two loops with arraycopy
// which will perform better on large arrays
if(lIdx < left) {
System.arraycopy(l, lIdx, a, aIdx, l.length-lIdx);
}
if(rIdx < right) {
System.arraycopy(r, rIdx, a, aIdx, r.length-rIdx);
}
return size;
}
由於您重視性能,因此應盡可能使用 System.arraycopy。 我還重命名了循環變量以使代碼更易於理解。
System.out.println(countBaad(new int[]{7,3,5,4,1}));
//prints:
//Merging [7] and [3]
//Merging [4] and [1]
//Merging [5] and [4, 1]
//Merging [7, 3] and [5, 4, 1]
// Found bad pair: (3,5)
// Found bad pair: (3,4)
//2
System.out.println(countBaad(new int[]{8,5,6,7,2,1}));
//prints:
//Merging [5] and [6]
// Found bad pair: (5,6)
//Merging [8] and [6, 5]
//Merging [2] and [1]
//Merging [7] and [2, 1]
//Merging [8, 6, 5] and [7, 2, 1]
// Found bad pair: (6,7)
// Found bad pair: (5,7)
//3
編輯#2
要從此方法中刪除副作用(排序),可以復制輸入數組,例如簡單調用Arrays.copyOf(hs, hs.length);
並傳入結果而不是原始結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.