zoukankan      html  css  js  c++  java
  • 归并法求逆序数之“Ultra-QuickSort”

    题目大意:

      给你一个上限为(5e5)的整数 n 。

      在给出 n 个非负整数,这些数上限是 999 999 999 。

      求出其中有多少个逆序数对。

      解释下逆序数对:

        比如在数列 1 ,2 ,5 ,4 ,3 中,

        1 的逆序数就是后面所有比它小的数字个数,即为 0 。

        2 同理 ,即为 0 。

        5 后面有 3 和 4 ,即为 2 。

        4 后面有一个 3 ,即为 1 。

        3 后面没有数字,即为 0 。

        所以在上述数列中,逆序数对有  0 + 0 + 2 + 1 + 0 == 3  个。

    解题思路:

      在归并的过程中检测单向移动距离之和(所谓单向  就是要么都计算往前移动的距离,要么相反,计算往后移动的距离)。

      比如 3  ,2 ,4 ,1 。(检查数字向前移动的距离和)

      第一步:3 和 2 调换 ,检查 3 向前移动了 1 个单位,数列变成:  2  3  4  1  

      第二步:4 和 1 调换 ,检查 4 向前移动了 1 个单位 ,数列变成:  2  3  1  4

      第三步:归并两个子数列 ,发现只有 1 向前移动了两个单位,而后再也不出现向前移动的数字,数列也变成最终的有序数列。

      如果计算向后移动的距离和也是同理:

        3 移动 1 个单位 , 4 移动 1 个单位 , 2 移动 1 个单位 , 3 又移动 1 个单位。

        加起来也是正好 4 个单位。

      所以这个数列的逆序数对就是 4 ,输出换行即可。

    AC代码:

     1 import java.util.*;
     2 
     3 public class Main{
     4 
     5     static long ans = 0L;
     6     static int num[] = new int[500005];
     7     static int temp[] = new int[500005];
     8 
     9     static void merge(int low,int mid,int high){
    10         int i = low; int j = mid + 1; int k = low;
    11         while(i <= mid && j <= high){  
    12             if (num[i] <= num[j]){  
    13                 temp[k ++] = num[i ++];  
    14             }  
    15             else{  
    16                 ans = ans + j - k ;
    17                  temp[k ++] = num[j ++];  
    18             }  
    19         }  
    20         while (i <= mid) {temp[k ++] = num[i ++];}  
    21         while (j <= high){temp[k ++] = num[j ++];}  
    22             for(i = low; i <= high; ++i){  
    23                 num[i] = temp[i];  
    24             }  
    25     }
    26     
    27     static void sort(int a,int b){
    28         if(a < b){
    29             int mid = (a + b) / 2;  
    30             sort(a, mid);  
    31             sort(mid + 1, b);  
    32             merge(a, mid, b);    
    33         }
    34     }
    35     
    36     public static void main(String[] args){
    37         Scanner sc = new Scanner(System.in);
    38         while(sc.hasNext()){
    39             int n = sc.nextInt();
    40             if(n == 0){break;}
    41             for(int i = 0;i < n;i ++){
    42                 num[i] = sc.nextInt();
    43             }
    44             sort(0,n - 1);
    45             System.out.println(ans); 
    46             ans = 0L;
    47         }
    48     }
    49 }

      此处再给出一个超时的代码,不过这个程序可以查看计算过程和排序过程,具体超时原因应该是出现了无用遍历。

    超时代码:

     1 import java.util.*;
     2 
     3 public class Main{
     4     
     5     static int ans = 0;
     6     
     7     static void print(int x[]){  
     8         for(int i = 0; i < x.length; i++){  
     9                     System.out.print(x[i] + "  ");  
    10                }System.out.println();  
    11         }
    12 
    13     static void mergeSort(int x[]){  
    14         sort(x,0,x.length - 1);  
    15     }
    16 
    17 
    18     static void sort(int arr[], int left, int right){  
    19         if (left >= right){return; } 
    20             int mid = (left + right) / 2;   
    21                sort(arr, left, mid);  
    22             sort(arr, mid + 1, right);   
    23             merge(arr, left, mid, right);  
    24             //print(data); 
    25         }  
    26 
    27     static void merge(int Array[], int index_L, int index_C, int index_R){  
    28             int Array_t[] = new int[Array.length];   
    29             int mid = index_C + 1;   
    30             int index_t = index_L;    
    31             int _t = index_L;  
    32             while (index_L <= index_C && mid <= index_R){    
    33                     if (Array[index_L] <= Array[mid]){  
    34                         Array_t[index_t ++] = Array[index_L ++];  
    35                     } 
    36             else{  
    37                 //System.out.println(mid - index_t);
    38                     ans = ans + mid - index_t;
    39                 //System.out.println("ans " + ans);
    40                            Array_t[index_t ++] = Array[mid ++];  
    41                     }  
    42             }  
    43             while (mid <= index_R) {  
    44                     Array_t[index_t ++] = Array[mid ++];  
    45             }  
    46             while (index_L <= index_C) {  
    47                     Array_t[index_t ++] = Array[index_L ++];  
    48             }    
    49             while (_t <= index_R) {  
    50                     Array[_t] = Array_t[_t ++];  
    51             }  
    52     }  
    53 
    54     public static void main(String[] args){
    55         Scanner sc = new Scanner(System.in);
    56         while(sc.hasNext()){
    57             int n = sc.nextInt();
    58             if(n == 0){break;}
    59             int in[] = new int[n];
    60             for(int i = 0;i < n;i ++){
    61                 in[i] = sc.nextInt();
    62             }
    63             //print(in);
    64             mergeSort(in);
    65             //print(in);
    66             System.out.println(ans); 
    67             ans = 0;
    68         }
    69     }
    70 }
  • 相关阅读:
    Swap Nodes in Pairs
    Search for a Range——稍微升级版的二分查找
    Set Matrix Zeroes——常数空间内完成
    Ubuntu系统---C++之Eclipse 开始工程项目
    Ubuntu系统---C++之Eclipse编译器 CDT插件安装
    Ubuntu系统---开机总会显示错误报告处理
    Ubuntu系统---C++之Eclipse IDE 编译器安装
    Ubuntu系统---终端下用g++进行c++项目
    Ubuntu系统---进行C++项目开发的工具
    YOLO---Darknet下的 GPU vs CPU 速度
  • 原文地址:https://www.cnblogs.com/love-fromAtoZ/p/7591651.html
Copyright © 2011-2022 走看看