2014-11-02 22 views
7

Tôi gặp sự cố thuật toán thú vị:Tìm số cặp chưa được sắp xếp trong một mảng

Cho số lượng cặp không được sắp xếp trong mảng đó, cho biết {1, 3, 2 }, câu trả lời là 1 vì {3, 2} không được đặt hàng và đối với mảng {3, 2, 1}, câu trả lời là 3 vì {3, 2}, {3, 1}, {2, 1} .

Rõ ràng, điều này có thể được giải quyết bằng vũ lực với thời gian chạy O (n^2) hoặc hoán đổi tất cả các cặp có thể sau đó loại bỏ các cặp không hợp lệ đó.

Câu hỏi của tôi là cơ thể nào có bất kỳ giải pháp nào tốt hơn và bạn sẽ làm như thế nào vì nó có vẻ như là một vấn đề lập trình động. Đoạn mã sẽ hữu ích

+0

Không, nó có thể giống như {1, 99, 4}. Tuy nhiên, tôi nghĩ rằng bạn có thể giả định không có bản sao trong mảng đó –

Trả lời

7

Có thể giải quyết vấn đề này trong thời gian O(n log n) bằng cách sử dụng cây tìm kiếm nhị phân cân bằng. Đây là mã giả của thuật toán này:

tree = an empty balanced binary search tree 
answer = 0 
for each element in the array: 
    answer += number of the elements in the tree greater then this element 
    add this element to the tree 
+0

Xin chào, bạn có thể vui lòng giải thích tại sao 'O (n log n) 'này không? Tôi không giỏi về sự phức tạp nhưng từ những gì tôi hiểu một 'for- loop' đơn nghĩa là' O (n) ' –

+3

Việc thêm một phần tử vào cây tìm kiếm nhị phân cân bằng là' O (log n) '. Điều này cũng đúng với việc đếm số phần tử lớn hơn số phần tử đã cho. Do đó, độ phức tạp là 'O (n * log n)' (tức là, mỗi lần lặp lại có thời gian 'O (log n)' – kraskevich

0

Bạn có thể sử dụng thuật toán sắp xếp hợp nhất đã sửa đổi. Hợp nhất sẽ giống như thế này.

merge(a, b): 
    i = 0 
    j = 0 
    c = new int[a.length+b.length] 
    inversions = 0 
    for(k = 0 ; k < Math.min(a.length, b.length); k++) 
     if(a[i] > b[j]): 
      inversions++ 
      c[k] = b[j] 
      j++ 
     else: 
      c[k] = a[i] 
      i++ 
    //dump the rest of the longer array in c 
    return inversions 

Hợp nhất được thực hiện trong thời gian O (n). Độ phức tạp thời gian của toàn bộ sắp xếp hợp nhất là O (n log n)

+0

Tại sao bạn cần biến 'c' trong trường hợp này? – Soravux

+0

bạn đang hợp nhất hai Vì vậy, bạn cần phải phân bổ một mảng thứ ba đủ lớn để giữ các phần tử của cả hai mảng nhỏ hơn. Nói cách khác, kích thước của mảng thứ ba phải là một trong hai mảng nhỏ hơn. Không cần thêm mảng, nhưng tôi thấy việc triển khai này đơn giản để minh họa ý tưởng sử dụng sắp xếp hợp nhất để đếm số cặp không theo thứ tự – turingcomplete

+1

Trong trường hợp đó, bạn không nên trả về 'c' cùng với' inversions'? , không phải chức năng chia tách (gọi là 'hợp nhất') không hội tụ? – Soravux

3

Bạn có thể sử dụng phiên bản hợp nhất đã sửa đổi để đếm số lần đảo ngược. Bí quyết là trong khi sáp nhập hai mảng phụ được sắp xếp, bạn có thể biết các yếu tố không đúng chỗ. Nếu có bất kỳ phần tử nào trong phần con bên phải cần phải đi trước các phần tử trong phần con bên trái, chúng là các phần tử đảo ngược. Tôi đã viết mã cho điều này trong python. Bạn có thể kiểm tra giải thích dưới đây để hiểu rõ hơn. Nếu bạn không thể hiểu được sắp xếp hợp nhất, tôi khuyên bạn nên revist sắp xếp hợp nhất sau đó điều này sẽ được trực quan.

def merge_sort(l): 
    if len(l) <= 1: 
     return (0, l) 
    else: 
     mid = len(l)/2 
     count_left, ll = merge_sort(l[0:mid]) 
     count_right, lr = merge_sort(l[mid:]) 
     count_merge, merged = merge(ll, lr) 
     total = count_left + count_right + count_merge 
     return total, merged 

def merge(left, right): 
    li, ri = 0, 0 
    merged = []   
    count = 0 
    while li < len(left) and ri < len(right): 
     if left[li] < right[ri]: 
      merged.append(left[li]) 
      li += 1 
     else: 
      count += 1 
      merged.append(right[ri]) 
      ri += 1 

    if li < len(left): 
     merged.extend(left[li:]) 
    elif ri < len(right): 
     merged.extend(right[ri:]) 
    return count, merged 

if __name__ == '__main__': 
    # example 
    l = [6, 1 , 2, 3, 4, 5] 
    print 'inverse pair count is %s'%merge_sort(l)[0] 
  • Merge sort chạy trong n * log (n) thời gian.
  • cho danh sách được chuyển l, merge_sort trả về một bộ (theo dạng (inversion_count, list)) của số nghịch đảo và danh sách được sắp xếp
  • Bước phối đếm đếm số nghịch đảo và lưu nó trong số biến.
Các vấn đề liên quan