应用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 <script type="math/tex" id="MathJax-Element-30">H</script>是树的高度。
网上的AVL树的解法:
Using Self-Balancing BST