Algorithm clock in Ques20201009

1. Problem description

Search engines on the Internet often need to compare information. For example, a person can estimate his interest in a variety of different information through the ranking of some things. For different ranking results, you can use the reverse order to evaluate the differences between them. Consider the arrangement i1, i2, …, in of 1, 2, …, n. If there are ij, ik such that j<k but ij>ik, then (ij, ik) is said to be a reverse order of this arrangement. The number of inverse sequences in an arrangement is called the inverse number of the arrangement. For example: arrangement 2 6 3 4 5 1 contains 8 reverse orders: (2, 1), (6, 3), (6, 4), (6, 5), (6, 1), (3, 1), (4, 1), (5, 1), its inverse number is 8. Among all n! permutations composed of 1, 2, …, n, the smallest inverse number is 0, the corresponding permutation is 1 2 3 4…n, and the largest inverse number is n(n-1) / 2, The corresponding arrangement is nn-1… 2 1. The greater the number of inverse numbers, the greater the degree of difference between the original arrangement.

Simply put: find the inverse ordinal

 

2. Ideas

Refer to the process of merging and sorting, post a sheet of merge and sorting steps as shown in Figure 1

 

Figure 1 The basis of merge sort

 In the process of merging and sorting, two sub-arrays are compared. At this time, three parameters of low, mid and high are passed in, and mid is the position of division. Setting two pointers j and h will compare arr[h] and arr[j], and throw the smaller one into the temp array. code show as below:

//利用归并排序
	// 关键词:递归 分治 归并 复杂度O(nlogn)      
    void merge(vector<int>& arr, int low, int mid, int high) {
        //merge函数将两部分,(分别排好序的子数组),合并成一个,再存于原数组arr
        int h, i, j, k;
        h = low; i = low; j = mid + 1; // h,j作为游标,i指向temp存放数组元素的游标
        int length = arr.size();
        vector<int> temp(length); // 这个temp数组是local的,长度为数组arr长度
        while (h <= mid && j <= high) { // 当两个集合都没有取尽时          
            if (arr[h] <= arr[j]) {
                temp[i] = arr[h];
                h++;
                // 如果S1的最小元素小于S2的最小元素,此时将S1[h]放入temp
           // 逆序数不增加

            }
            else {
                // 如果S1的最小元素大于S2的最小元素x,此时将S2[j]放入temp
            // 此时S1中的每个元素都和x构成逆序
                count = count + (mid - h) + 1;
                temp[i] = arr[j];
                j++;
            }
            i++;         
        }
        if (h > mid) { // 当第一子组元素被 取尽,而第二组元素未被取尽时
            for (int k = j; k <= high; k++) {
                temp[i] = arr[k];
                i++;
            }
        }
        else { // 当第2组取尽,第一组未被取尽时
            for (int k = h; k <= mid; k++) {
                temp[i] = arr[k];
                i++;
            }
        }
        for (int k = low; k <= high; k++) {//将临时数组temp中的元素再赋值给arr
            arr[k] = temp[k];
        }
    }
    void mergeSort(vector<int>& arr, int low, int high) {
        // arr[low..high]是一个全程数组,含有high-low+1个待排序元素
        if (low < high) {
            int mid = low + (high - low) / 2;
            mergeSort(arr, low, mid);
            mergeSort(arr, mid + 1, high);
            merge(arr, low, mid, high);
        }
    }	

3. The key point of finding the inverse ordinal number

Analyze the merge sort process. When merging two sub-arrays, two pointers j and h will be set. If the smallest element of the array S1 is less than the smallest element of S2, then S1[h] is placed in the temporary array temp, and the reverse number does not increase.

If the smallest element of S1 is greater than the smallest element x of S2, then S2[j] is put into the temporary array temp. At this time, each element in S1 forms a reverse order with x, so the added reverse number is the existing left side The number of remaining elements in the array is expressed as (mid-h) in the code . So add this line of count to the else judgment in the code:

 

4. Running effect

//Ques20201008
int main() {
    Ques20201008 qus=Ques20201008();
    qus.test();
	return 0;
}

int count = 0;//记录逆序数
	void test() {
        vector<int> arrs = { 2, 6, 3 ,4 ,5, 1 };
        mergeSort(arrs,0,5);
        cout << count;
	}

Arrangement 2 6 3 4 5 1 contains 8 reverse orders: (2,1), (6,3), (6,4), (6,5), (6,1), (3,1), (4 ,1), (5,1), its inverse number is 8.

 

Guess you like

Origin blog.csdn.net/Toky_min/article/details/108968421