Use the merge sort method to calculate the number of reverse-order logarithm in a sequence (detailed description) and reverse-order logarithm
Preface
I have encountered a reverse order query problem today. After thinking about it, I would like to summarize it. I have learned a lot of methods, and I have answered some questions that I have never been able to solve.
Body
Let's start with a simple question:
Analysis: in the question, insert sorting is used, that is, to calculate the number of exchanges during the sorting process. According to the principle of insert sorting, set the first one, then set the first two, and so on, as long as the switch is done, I will add one for the number of times, but in fact, we have been following the original sequence, so (well, the point is coming) what we want to insert is the position in front of a number larger than me. That is to say, the number of times I want to swap is the number of numbers larger than me, so I think there is no need to exchange it. Just compare it with the preceding number. If there is a bigger number than you are, add one. In fact, this is similar to the number of reverse orders we have learned on our line, that is, the number of reverse orders.
The following code is written:
1 #include<stdio.h> 2 int main() { 3 int n,m; 4 5 scanf("%d\n",&n); 6 7 int count = 0; 8 for(int i=0; i < n; i++) { 9 scanf("%d\n",&m);10 int ch[m];11 for(int j=0; j < m; j++) {12 scanf("%d",&ch[j]);13 }14 15 for(int k=1; k < m; k++) {16 for(int l=0; l < k; l++) {17 if(ch[k] < ch[l]) count++;18 }19 }20 }21 printf("%d\n",count);22 23 return 0;24 }
The code here is common and easy to understand. Of course, you can optimize algorithms in two loops. If you are interested, try it on your own. You can also find another method to calculate the number of reverse orders.
Well, next, let's talk about the key issues. I believe many people can solve the previous problems, but the following problems are not so easy. We need to think about them and some code skills.
Note: Hint: if you use a two-byte loop to find the answer, it will exceed the system time limit.
Therefore, you must seek algorithms with low complexity. As prompted, you must first familiarize yourself with the principle of Merge Sorting to calculate Reverse Order pairs during the merge process, and then look at the problems. So I made an algorithm on the paper. First, I continued to divide the two into two groups. Then, I divided them into two groups, each of which has a number. If the latter is larger than the former one, that is, a reverse order number pair, then add one, and put a small number in front. Then, after merging, a group of numbers containing two numbers is obtained. Next, compare the two numbers in each group. If the first number in the second group is greater than the first number in the first group, add two because it is smaller than all the numbers in the previous group. Then merge. And so on. The principle is: if the number of the next group is smaller than the number of I in the previous group, the reverse order logarithm is added (mid-I + 1 ).
Although I understand the principle, I think it is still difficult for those who are not familiar with it, especially some of the skills.
Not much. Analyze how to write the code first, and write the framework first:
1 # include <stdio. h> 2 3 int count = 0; // Number of reverse orders pairs 4 void mergeSort (int lo, int hi) {5 6} 7 8 int main () {9 int N; 10 scanf ("% d", & N); 11 12 for (int I = 0; I <N; I ++) {13 scanf ("% d ", & ch [I]); 14} 15 16 mergeSort (0, N-1); // merge sort 17 18 printf ("% d \ n", count); 19 return 0; 20}
This part of the framework should be understandable. Next we will talk about merging. The first principle is to first divide the two parts, sort them separately, and then merge them.
1 void mergeSort (int lo, int hi) {2 if (lo
In fact, this is almost a framework, but pay attention to the lo
Then the key is to merge this part, and set the tag points. The conditions for the I = lo and j = mid + 1 loops should be
1 int i = lo;2 int j = mid + 1;3 while(i <= mid&&j <= hi) {4 5 }
If the number I of the preceding group is greater than the number of the following group, the count value is added with mid-I + 1. Of course, a temporary array is required for merging to store the number of positions changed,
1 int i = lo; 2 int j = mid + 1; 3 int x = lo; 4 5 while(i <= mid&&j <= hi) { 6 if ( ch[i] > ch[j]) { 7 count += mid - i + 1; 8 temp[x++] = ch[j++]; 9 }10 else {11 temp[x++] = ch[i++];12 }13 }
Of course, there is another point to note. If the number of the previous Group is already exceeded, and the number of the subsequent group is no longer completed, the loop is exited, then this temporary array is incomplete because it does not merge all the numbers. Add
1 while(i <= mid) temp[x++] = ch[i++];2 while(j <= hi) temp[x++] = ch[j++];
Then, of course, we also need to return the value of this temporary array to the original array so that the array can be merged in the next round.
1 for(int k = lo; k <= hi ; k++)2 ch[k] = temp[k];
Okay, so we can write the entire code.
This is the complete source code:
1 # include <stdio. h> 2 3 void Merge (int, int, int); 4 void mergeSort (int, int); 5 6 int ch [20000], temp [20000]; // The maximum number is 20000. Note that the global variable is easy to use. 7 int count = 0; // The number of reverse orders. It must be a global variable, so that it can be continuously added no matter how recursion. The original idea was to return the number of backward-order pairs in recursion and accumulate them continuously. This is more difficult to achieve. This is directly a global variable, which is convenient and concise. 8 9 void mergeSort (int lo, int hi) {// The recursive function performs binary sorting and merges them. 10 if (lo
Summary
The biggest benefit here is that count is a global variable, so we can continue accumulating in the continuous recursion. my original idea was to check whether the number of reverse-order pairs can be returned in recursion, alternatively, the number of reverse pairs added to the parameter is always transmitted. This time I finally got the answer, and the temporary array he created during the merge was also clever, and finally assigned a value to the original array. The best part is recursion, which is hard to understand and think about. It seems that recursion will be used in the future.
12:37:30