And the number of merge sort of the reverse of the array

Merge sort

First, we recall the main idea of ​​merge sort:

  1. First, consider how to merge two ordered sequences? This method is the following code merge method, if we could merge the two sub-ordered sequence, then it can be a short sub-sequences into longer sequences, until the completion of sequencing the source array.
  2. How to get the most orderly sequences begin to merge it? Through continuous array divided until the time of each sub-sequence only one element, the second is an ordered sequence, and this way, we can achieve the merger of the sub-ordered sequence.

The study recommended specific understanding of this video explain , the teacher said very carefully, to follow their own will be able to understand it again using familiar language implementation.

In this algorithm where we need to pay attention to several points:

  1. We have to sort the original array, it needs a temporary array tmp, two ordered sequences, each row of the elements necessary to good order placed tmp, then place the elements tmp from the pound back to the original array, we can tmp merger will be passed as a parameter into the beginning, not the new consolidation method tmp in it, in that case will continue to declare an array of algorithms throughout the run, destroy arrays.
  2. To merge two ordered sequences, conventional thinking is relatively backward scratch, who put little who put tmp, subscript tmp from scratch; but for some variants, we need to compare is from the back, who who put great on the back of tmp, tmp index from the end of the beginning, as the title describes the extension after us: ask for the number of array in reverse order. It will use to this detail.
  3. The best and worst time complexity of the algorithm is O (nlgn), and is a stable sort.

 

Java implementation 

. 1  public  class MyMergeSort {
 2      public  static  void mergesort ( int [] the nums) {
 . 3          msort (the nums, new new  int [nums.length], 0,-nums.length. 1 );
 . 4      }
 . 5  
. 6      / ** 
. 7       * first division : has only one dividing element is divided into a sequence
 . 8       * @param the nums original array
 . 9       * @param tmp temporary array
 10       * @param leftStart left sequence initiates subscript
 . 11       * @param rightEnd sequences to the right end of the subscript
 12      * / 
13 is      Private  static  void msort ( int [] the nums, int [] tmp, int leftStart, int rightEnd) {
 14          IF (leftStart == rightEnd) {
 15              return ;
 16          }
 . 17          // divided into two 
18 is          int MID = + leftStart (rightEnd-leftStart) / 2 ;
 . 19          // points left subarray 
20 is          msort (the nums, tmp, leftStart, MID);
 21 is          // farther to the right sub-array 
22 is          msort (the nums, tmp, MID +. 1 , rightEnd);
 twenty three         // merge. 
24          Merge (leftStart, MID +. 1 , rightEnd, tmp, the nums);
 25      }
 26 is  
27      / ** 
28       * then rule: two ordered subsequences are combined.
29       * @param leftStart left start index subsequence
 30       * @param start index rightStart right sequence
 31 is       * @param rightEnd end of the right index subsequence
 32       * @param tmp temporary array, the results before and after the two sub-arrays sorting results are saved in the tmp
 33 is       * @param the nums original array
 34 is       * / 
35      Private  static  void Merge (int leftStart, int rightStart, int rightEnd, int[] tmp, int[] nums) {
36         int leftEnd = rightStart-1;
37         // tmpStart 代表此次元素放在 tmp 的哪个下标位置,
38         int tmpStart = leftStart;
39         int length = rightEnd-leftStart+1;
40         while (leftStart <= leftEnd && rightStart <=rightEnd) {
41             // 降序
42             //tmp[tmpStart ++] = nums[leftStart] > nums[rightStart] ? nums[leftStart++] : nums[rightStart++];
43 
44             // 升序
45             tmp[tmpStart ++] = nums[leftStart] < nums[rightStart] ? nums[leftStart++] : nums[rightStart++];
46         }
47         while (leftStart <= leftEnd) {
48              tmp[tmpStart ++] = nums[leftStart ++];
49         }
50         while (rightStart <= rightEnd) {
51             tmp[tmpStart ++] = nums[rightStart ++];
52         }
53         // 将 tmp 里有序的元素捣回到原数组。
54         for (int i=0; i<length; i++, rightEnd--) {
55             nums[rightEnd] = tmp[rightEnd];
56         }
57     }
58     
59     public static void main(String[] args) {
60         int[] nums = new int[] { 9, 8, 7, 6, 5, 4, 3, 2, 10 };
61         mergeSort(nums);
62         for (int x : nums) {
63             System.out.print(x+ " ");
64         }
65     }
66 }

 

expand

Seeking to reverse the array

  What is the reverse of it, for the array nums, if satisfied

i < j && nums[i] > nums[j]

则称 nums[i] 和 nums[j] 就构成了一对逆序对。举个例子:对于数组:[ 1,5,3,2,6 ],共存在 3 组逆序对,分别是 [5, 3]、[5,2]、[3,2] 。对于最简单的思路就是用两次 for 循环对每个元素查找其构成的逆序对数量,时间复杂度为O(n^2)。如果借用归并排序的思想,可以达到和归并排序一样的时间复杂度O(nlgn)。

  对原数组进行归并排序,在合并操作的时候就可以获得前后两个子序列的逆序对。这里是从子序列的尾部往前移动的。

Java实现

 

 1 public class CountReverse {
 2     public static int inversePairs(int[] nums){
 3         if( nums == null ||nums.length <= 1) {
 4             return 0;
 5         }
 6         int[] tmp = new int[nums.length];
 7 
 8         return mergeCount(nums, tmp, 0, nums.length-1);
 9     }
10 
11     public static int mergeCount(int[] nums, int[] tmp, int leftStart, int rightEnd){
12         if(leftStart == rightEnd){
13             tmp[leftStart] = nums[leftStart];
14             return 0;
15         }
16         int mid = leftStart + (rightEnd - leftStart)/2;
17         
18         int leftCount = mergeCount(nums, tmp, leftStart, mid);
19         int rightCount = mergeCount(nums, tmp, mid+1, rightEnd);
20 
21         int leftEnd = mid;// i 初始化为前半段最后一个数字的下标
22 
23         int tmpEnd = rightEnd;//辅助数组复制的数组的最后一个数字的下标
24         
25         int count = 0; //计数--逆序对的数目
26 
27         while(leftStart <= leftEnd && mid+1 <= rightEnd){
28             if(nums[leftEnd] > nums[rightEnd]){
29                 tmp[tmpEnd --] = nums[leftEnd --];
30                 // 因为 是两个有序的子序列。
31                 count += rightEnd - mid;
32             }else{
33                 tmp[tmpEnd--] = nums[rightEnd--];
34             }
35         }
36 
37         while (leftEnd >= leftStart) {
38             tmp[tmpEnd --] = nums[leftEnd --];
39         }
40 
41         while (rightEnd >= mid + 1) {
42             tmp[tmpEnd --] = nums[rightEnd --];
43         }
44         
45         return leftCount + rightCount + count;
46     }
47 
48     public static void main(String[] args) {
49         int[] nums = new int[] {1, 5, 3, 2, 6};
50         System.out.println(inversePairs(nums));
51     }
52 }

 

 

 

 

Guess you like

Origin www.cnblogs.com/dogeLife/p/11428558.html