從求逆序對和mergeSort談起(2)

應用mergeSort的思想,可以解決許多和下標有關的問題。看了有關題的提示,發現有些能用Divide and Conqure解決的,也可以用 Binary Search Tree,Segment Tree,Binary Index Tree解決。它們都可以把原始的時間複雜度爲O(n2) 的算法降低爲O(nlogn) .
下面從求數組的逆序數對這一問題,用不同的方法去解決。
Count inversions in an array
Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum.

Two elements a[i] and a[j] form an inversion if 
 a[i] > a[j] and i < j. For simplicity, we may 
 assume that all elements are unique.

 Example:
 Input:  arr[] = {8, 4, 2, 1}
 Output: 6
 Given array has six inversions (8,4), (4,2),
 (8,2), (8,1), (4,1), (2,1).     
/*
1. 構造BST
 eg. nums=[3,2,2,6,1]
 每次插入一個新的節點之前,都要計數現有的逆序對,即比要插入值小的個數
 stp1: 插入1;1(less=0,same=1)
 stp2:插入6;search(root,6)=1;
          1(0,1)
           \
            6(0,1)
 stp3:插入2;search(root,2)=1;
          1(0,1)
           \
            6(1,1)
           /
          2 (0,1)
  stp4:插入2;search(root,2)=1;
          1(0,1)
           \
            6(2,1)
           /
          2 (0,2)
  stp5:插入3;search(root,3)=3;
          1(0,1)
           \
            6(2,1)
           /
          2 (0,2)
           \
           3(0,1)
  總的逆序數:1+1+1+3=6
  */

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Node{
    int val;
    int less,same=1;
    Node* left,*right;
    Node(int v):val(v){less=0;left=right=NULL;}
};
Node* insert(int num,Node *root)
{
    if(!root) return new Node(num);
    if(num==root->val) root->same++;
    else if(root->val>num)
    {
        root->less++;
        root->left=insert(num,root->left);
    }else
    root->right=insert(num,root->right);
    return root;
}
int search(Node* root,int num)
{
    if(!root) return 0;
    int res=0;
    if(root->val<num) res+=search(root->right,num)+root->same+root->less;
    else res=search(root->left,num);
    return res;
}
int getInvCount(vector<int> &arr)
{
    int ans=0,n=arr.size();
    Node* root=NULL;
    for(int i=n-1;i>=0;i--)
    {
        ans+=search(root,arr[i]);
    root=insert(arr[i],root);
    }
    return ans;
}
int main()
{
   vector<int> arr={3,2,2,6,1};
  printf(" Number of inversions are %d \n", getInvCount(arr));
   return 0;
}

這裏用的只是BST,如果遇到特殊情況,如[1,2,3,4],複雜度就會是 O(n2) ,如果應用平衡二叉樹,RBT、AVL,複雜度會是O(nlogn) 。這裏插入和查詢的操作都是O(H)=O(logn) , H 是樹的高度。

網上的AVL樹的解法:
Using Self-Balancing BST

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章