从求逆序对和mergeSort谈起(2)

5 篇文章 0 订阅

应用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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值