亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在數組中計數反轉

在數組中計數反轉

慕勒3428872 2019-06-26 15:59:48
在數組中計數反轉我正在設計一個算法來執行以下操作:給定的數組A[1... n],為每一個i < j,找到所有的反轉對,這樣A[i] > A[j]..我使用合并排序和將數組A復制到數組B,然后比較這兩個數組,但我很難了解如何使用它來找到倒置的數量。如有任何提示或幫助,將不勝感激。
查看完整描述

3 回答

?
LEATH

TA貢獻1936條經驗 獲得超7個贊

這里是Java中的O(N Logn)解決方案。

long merge(int[] arr, int[] left, int[] right) {
    int i = 0, j = 0, count = 0;
    while (i < left.length || j < right.length) {
        if (i == left.length) {
            arr[i+j] = right[j];
            j++;
        } else if (j == right.length) {
            arr[i+j] = left[i];
            i++;
        } else if (left[i] <= right[j]) {
            arr[i+j] = left[i];
            i++;                
        } else {
            arr[i+j] = right[j];
            count += left.length-i;
            j++;
        }
    }
    return count;
}

long invCount(int[] arr) {
    if (arr.length < 2)
        return 0;

    int m = (arr.length + 1) / 2;
    int left[] = Arrays.copyOfRange(arr, 0, m);
    int right[] = Arrays.copyOfRange(arr, m, arr.length);

    return invCount(left) + invCount(right) + merge(arr, left, right);
}

這幾乎是正常的合并排序,整個魔術隱藏在合并功能中。注意,當排序算法移除反轉時。當合并算法計算被移除的倒置數時(有人可能會說)。

移除反轉的唯一時刻是算法從數組的右側提取元素并將其合并到主數組中。此操作移除的反轉數是從要合并的左數組中留下的元素數。*)

希望有足夠的解釋。


查看完整回答
反對 回復 2019-06-26
?
飲歌長嘯

TA貢獻1951條經驗 獲得超3個贊

我通過以下方法在O(n*log n)時間內找到了它。

  1. 合并排序數組A并創建副本(數組B)
  2. 取A[1],通過二進制搜索在排序數組B中找到其位置。這個元素的倒置數將比它在B中位置的索引數少一個,因為在A的第一個元素后面出現的每一個較低的數都是一個反轉。

    2A.累積反轉的數目,以對抗變量num_inversion。

    2B.將A[1]從數組A及其在數組B中的相應位置移除

  3. 從步驟2重新運行,直到A中沒有更多的元素。

下面是這個算法的一個例子。原始陣列A=(6,9,1,14,8,12,3,2)

1:合并排序和復制到數組B

B=(1、2、3、6、8、9、12、14)

2:采用A[1]和二進制搜索在數組B中找到它

A[1]=6

B=(1,2,3,6, 8, 9, 12, 14)

6位于B陣列的第4位,因此有3處倒置。我們之所以知道這一點,是因為6位于數組A中的第一個位置,因此,隨后出現在數組A中的任何較低值元素的索引都將為j>i(因為在本例中,I為1)。

2.b:從數組A中移除A[1],也從數組B中的相應位置刪除A[1](刪除粗體元素)。

A=(6, 9, 1, 14, 8, 12, 3, 2) = (9, 1, 14, 8, 12, 3, 2)

B=(1,2,3,6, 8, 9, 12, 14) = (1, 2, 3, 8, 9, 12, 14)

3:在新的A和B數組上重新運行步驟2。

A[1]=9

B=(1、2、3、8、9、12、14)

9現在位于陣列B的第5位,因此有4處倒置。我們之所以知道這一點,是因為9位于數組A中的第一個位置,因此隨后出現的任何較低值元素的索引都將為j>i(因為在本例中,I再次為1)。將A[1]從數組A中移除,并從數組B中的相應位置刪除A[1](刪除粗體元素)

A=(9, 1, 14, 8, 12, 3, 2) = (1, 14, 8, 12, 3, 2)

B=(1,2,3,8,9, 12, 14) = (1, 2, 3, 8, 12, 14)

在循環完成后,繼續這種方式將給出數組A的反轉總數。

步驟1(合并排序)需要執行O(n*logn)。步驟2將執行n次,每次執行將執行一個二進制搜索,需要O(Logn)來運行總共O(n*logn)。因此,總運行時間為O(n*log n)+O(n*log n)=O(n*log n)。

謝謝你的幫助。在一張紙上寫出樣本數組確實有助于將問題可視化。


查看完整回答
反對 回復 2019-06-26
?
POPMUISE

TA貢獻1765條經驗 獲得超5個贊

用Python

# O(n log n)

def count_inversion(lst):
    return merge_count_inversion(lst)[1]

def merge_count_inversion(lst):
    if len(lst) <= 1:
        return lst, 0
    middle = int( len(lst) / 2 )
    left, a = merge_count_inversion(lst[:middle])
    right, b = merge_count_inversion(lst[middle:])
    result, c = merge_count_split_inversion(left, right)
    return result, (a + b + c)

def merge_count_split_inversion(left, right):
    result = []
    count = 0
    i, j = 0, 0
    left_len = len(left)
    while i < left_len and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            count += left_len - i
            j += 1
    result += left[i:]
    result += right[j:]
    return result, count        


#test code
input_array_1 = []  #0
input_array_2 = [1] #0
input_array_3 = [1, 5]  #0
input_array_4 = [4, 1] #1
input_array_5 = [4, 1, 2, 3, 9] #3
input_array_6 = [4, 1, 3, 2, 9, 5]  #5
input_array_7 = [4, 1, 3, 2, 9, 1]  #8

print count_inversion(input_array_1)
print count_inversion(input_array_2)
print count_inversion(input_array_3)
print count_inversion(input_array_4)
print count_inversion(input_array_5)
print count_inversion(input_array_6)
print count_inversion(input_array_7)


查看完整回答
反對 回復 2019-06-26
  • 3 回答
  • 0 關注
  • 877 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號