📜  计算数组中的反转|设置4(使用特里)

📅  最后修改于: 2021-04-17 13:26:00             🧑  作者: Mango

数组的反转计数指示–数组要排序的距离(或距离)。如果已对数组进行排序,则反转计数为0。如果以相反顺序对数组进行排序,则反转计数为最大。

因此,我们的任务是计算数组中的反转次数。那是这样的一对元素(a [i],a [j])的数量:

  • a [i]> a [j]并且

范例

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). 

Input: arr[] = { 1, 20, 6, 4, 5 }    
Output: 5
  1. 天真的和修改的合并排序
  2. 使用AVL树
  3. 使用BIT

方法:
我们将在数组中向后迭代,并将每个元素存储到Trie中。要在Trie中存储号码,我们
必须将数字分解为二进制形式,如果该位为0,则表示我们将该位存储到当前节点的左指针中;如果为1 ,则将其存储到当前节点的右指针中,并相应地进行更改当前节点。我们还将维护该计数,该计数表示直到该节点为止,有多少个数字遵循相同的路径。
特里节点的结构

struct node{
  int count; 
  node* left;
  node* right;
};

在任何时候,当我们存储这些位时,我们碰巧移至右指针(即位为1),我们将检查左子级是否存在,这意味着存在小于当前数字的数字。被存储到Trie中时,这些数字仅是反转计数,因此我们会将其添加到计数中。
下面是实施方法

C++
// C++ implementation
#include 
using namespace std;
 
// Structure of the node
struct Node {
    int count;
    Node* left;
    Node* right;
};
 
// function to initialize
// new node
Node* makeNewNode()
{
    Node* temp = new Node;
    temp->count = 1;
    temp->left = NULL;
    temp->right = NULL;
    return temp;
}
 
// Insert element in trie
void insertElement(int num,
                   Node* root,
                   int& ans)
{
    // Converting the number
    // into binary form
    for (int i = 63; i >= 0; i--) {
        // Checking if the i-th
        // bit ios set or not
        int a = (num & (1 << i));
 
        // If the bit is 1
        if (a != 0) {
            // if the bit is 1 that means
            // we have to go to the right
            // but we also checks if left
            // pointer  exists i.e there is
            // at least a number smaller than
            // the current number already in
            // the trie we add that count
            // to ans
            if (root->left != NULL)
                ans += root->left->count;
 
            // If right pointer is not NULL
            // we just iterate to that
            // position and increment the count
            if (root->right != NULL) {
                root = root->right;
                root->count += 1;
            }
 
            // If right is NULL we add a new
            // node over there and initialize
            // the count with 1
            else {
                Node* temp = makeNewNode();
                root->right = temp;
                root = root->right;
            }
        }
 
        // if the bit is 0
        else {
            // We have to iterate to left,
            // we first check if left
            // exists? if yes then change
            // the root and the count
            if (root->left != NULL) {
                root = root->left;
                root->count++;
            }
 
            // otherwise we create
            // the left node
            else {
                Node* temp = makeNewNode();
                root->left = temp;
                root = root->left;
            }
        }
    }
}
 
// function to count
// the inversions
int getInvCount(int arr[], int n)
{
    Node* head = makeNewNode();
    int ans = 0;
    for (int i = n - 1; i >= 0; i--) {
        // inserting each element in Trie
        insertElement(arr[i],
                      head,
                      ans);
    }
 
    return ans;
}
 
// Driver Code
int main()
{
    int arr[] = { 8, 4, 2, 1 };
    int n = sizeof(arr) / sizeof(int);
 
    cout << "Number of inversions are : "
         << getInvCount(arr, n);
    return 0;
}


Java
// Java implementation of above idea
import java.util.*;
 
class GFG
{
 
// Structure of the node
static class Node
{
    int count;
    Node left;
    Node right;
};
static int ans;
 
// function to initialize
// new node
static Node makeNewNode()
{
    Node temp = new Node();
    temp.count = 1;
    temp.left = null;
    temp.right = null;
    return temp;
}
 
// Insert element in trie
static void insertElement(int num,
                Node root)
{
    // Converting the number
    // into binary form
    for (int i = 63; i >= 0; i--)
    {
        // Checking if the i-th
        // bit ios set or not
        int a = (num & (1 << i));
 
        // If the bit is 1
        if (a != 0)
        {
            // if the bit is 1 that means
            // we have to go to the right
            // but we also checks if left
            // pointer exists i.e there is
            // at least a number smaller than
            // the current number already in
            // the trie we add that count
            // to ans
            if (root.left != null)
                ans += root.left.count;
 
            // If right pointer is not null
            // we just iterate to that
            // position and increment the count
            if (root.right != null)
            {
                root = root.right;
                root.count += 1;
            }
 
            // If right is null we add a new
            // node over there and initialize
            // the count with 1
            else
            {
                Node temp = makeNewNode();
                root.right = temp;
                root = root.right;
            }
        }
 
        // if the bit is 0
        else
        {
            // We have to iterate to left,
            // we first check if left
            // exists? if yes then change
            // the root and the count
            if (root.left != null)
            {
                root = root.left;
                root.count++;
            }
 
            // otherwise we create
            // the left node
            else
            {
                Node temp = makeNewNode();
                root.left = temp;
                root = root.left;
            }
        }
    }
}
 
// function to count
// the inversions
static int getInvCount(int arr[], int n)
{
    Node head = makeNewNode();
    ans = 0;
    for (int i = n - 1; i >= 0; i--)
    {
        // inserting each element in Trie
        insertElement(arr[i],
                    head);
    }
 
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 8, 4, 2, 1 };
    int n = arr.length;
 
    System.out.print("Number of inversions are : "
        + getInvCount(arr, n));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 implementation
  
# Structure of the node
class Node:
     
    def __init__(self):
         
        self.left = self.right = None
        self.count = 1
 
# function to initialize
# new node
def makeNewNode():
     
    temp = Node()
    return temp
 
# Insert element in trie
def insertElement(num, root, ans):
 
    # Converting the number
    # into binary form
    for i in range(63, -1, -1):
     
        # Checking if the i-th
        # bit ios set or not
        a = (num & (1 << i));
  
        # If the bit is 1
        if (a != 0):
       
            # if the bit is 1 that means
            # we have to go to the right
            # but we also checks if left
            # pointer  exists i.e there is
            # at least a number smaller than
            # the current number already in
            # the trie we add that count
            # to ans
            if (root.left != None):
                ans += root.left.count;
  
            # If right pointer is not None
            # we just iterate to that
            # position and increment the count
            if (root.right != None):
                root = root.right;
                root.count += 1;
             
            # If right is None we add a new
            # node over there and initialize
            # the count with 1
            else:
                temp = makeNewNode();
                root.right = temp;
                root = root.right;
      
        # if the bit is 0
        else:
           
            # We have to iterate to left,
            # we first check if left
            # exists? if yes then change
            # the root and the count
            if (root.left != None):
                root = root.left;
                root.count += 1
  
            # otherwise we create
            # the left node
            else:
                temp = makeNewNode();
                root.left = temp;
                root = root.left;
    return ans
 
# function to count
# the inversions
def getInvCount(arr, n):
 
    head = makeNewNode();
    ans = 0;
     
    for i in range(n - 1 ,-1, -1):
     
        # inserting each element in Trie
        ans = insertElement(arr[i], head, ans);
  
    return ans;
 
# Driver Code
if __name__=='__main__':
 
    arr = [ 8, 4, 2, 1 ]
     
    n = len(arr)
     
    print("Number of inversions are : " + str(getInvCount(arr, n)))
 
    # This code is contributed by rutvik_56


C#
// C# implementation of above idea
using System;
 
class GFG
{
 
// Structure of the node
public class Node
{
    public int count;
    public Node left;
    public Node right;
};
static int ans;
 
// function to initialize
// new node
static Node makeNewNode()
{
    Node temp = new Node();
    temp.count = 1;
    temp.left = null;
    temp.right = null;
    return temp;
}
 
// Insert element in trie
static void insertElement(int num,
                         Node root)
{
    // Converting the number
    // into binary form
    for (int i = 63; i >= 0; i--)
    {
        // Checking if the i-th
        // bit ios set or not
        int a = (num & (1 << i));
 
        // If the bit is 1
        if (a != 0)
        {
            // if the bit is 1 that means
            // we have to go to the right
            // but we also checks if left
            // pointer exists i.e there is
            // at least a number smaller than
            // the current number already in
            // the trie we add that count
            // to ans
            if (root.left != null)
                ans += root.left.count;
 
            // If right pointer is not null
            // we just iterate to that
            // position and increment the count
            if (root.right != null)
            {
                root = root.right;
                root.count += 1;
            }
 
            // If right is null we add a new
            // node over there and initialize
            // the count with 1
            else
            {
                Node temp = makeNewNode();
                root.right = temp;
                root = root.right;
            }
        }
 
        // if the bit is 0
        else
        {
            // We have to iterate to left,
            // we first check if left
            // exists? if yes then change
            // the root and the count
            if (root.left != null)
            {
                root = root.left;
                root.count++;
            }
 
            // otherwise we create
            // the left node
            else
            {
                Node temp = makeNewNode();
                root.left = temp;
                root = root.left;
            }
        }
    }
}
 
// function to count the inversions
static int getInvCount(int []arr, int n)
{
    Node head = makeNewNode();
    ans = 0;
    for (int i = n - 1; i >= 0; i--)
    {
        // inserting each element in Trie
        insertElement(arr[i], head);
    }
    return ans;
}
 
// Driver Code
public static void Main(String[] args)
{
    int []arr = { 8, 4, 2, 1 };
    int n = arr.Length;
 
    Console.Write("Number of inversions are : " +
                            getInvCount(arr, n));
}
}
 
// This code is contributed by 29AjayKumar


输出:
Number of inversions are : 6

时间复杂度: O(Nlog(N))
辅助空间O(Nlog(N))