[Speaking algorithm small class] Use the divide and conquer method (based on the idea of merging and sorting) to find the inverse number of a permutation (O(n^2)→O(n log n))

Insert picture description here

Divide and conquer

Pre-knowledge: merge and sort.
We have proved the correctness of the merge sort. As long as the merge sort algorithm is slightly modified, the time complexity of finding the inverse number of a permutation can be reduced from O(n^2) to O(n log⁡n).
Divide an arrangement P into two parts P_1 and P_2 as evenly as possible. Then the
inverse ordinal number of P τ§=τ(P_1 )+τ(P_2 )+τ_Merge
Obviously, τ(P_1) and τ(P_2) represent the inverse ordinal numbers in the range of P_1 and P_2 that are solved recursively. And τ_Merge will cover all the missed cases, that is, the two elements a_i, a_j that form the reverse order pair (a_i, a_j), i<j, a_i>a_j satisfy a_i∈P_1, a_j∈P_2.
In the process of merging and sorting, the step of merging two ordered (ascending) sequence is:
set a temporary sequence t for merging.
The pointers i and j point to the beginning of the two sub-arrays respectively. The range of the sub-sequence is _begin to _mid, _mid + 1 to _end.
Constantly take an element from each of the two sub-arrays (that is, the elements pointed to by pointers i and j) for comparison, put the smaller number in the array t, and the corresponding pointer is incremented (when the two elements are equal, the address is compared by default The number in the lower array, that is, the number pointed to by i is put into t). When one of the sub-sequences is taken out, the cycle ends.
Copy all the elements of the sub-sequence whose elements have not been taken to the sequence t.
Suppose the two numbers taken out from the two sequence of ordinal numbers P_1 and P_2 of length m and n are x_i, y_j respectively, and the subscripts represent their positions in the sequence of ordinal numbers. If x_i>y_j is found in each comparison, and the sequence is known to be in ascending order, then
x_k>y_j, k=i,i+1,...,m, x_k∈P_1,y_j∈P_2
means that m is found -i+1 pairs in reverse order. That is, τ_Merge=m-i+1.
Code:

template<class _Ty> size_t merge(_Ty* _begin, _Ty* _mid, _Ty* _end) {
    
    
	const auto l = _end - _begin + 1; size_t tau = 0;
	_Ty* t = new _Ty[l], * i = _begin, * j = _mid + 1, * k = t;
	while (i <= _mid && j <= _end) {
    
    
		if (*i <= *j) {
    
     *k = *i; ++i; ++k; }
		else {
    
     *k = *j; ++j; ++k; tau += _mid - i + 1; }
	}
	while (i <= _mid) {
    
     *k = *i; ++i; ++k; }
	while (j <= _end) {
    
     *k = *j; ++j; ++k; }
	std::copy(t, t + l, _begin);
	delete[] t;
	return tau;
}

template<class _Ty> size_t inversion_count(_Ty* _begin, _Ty* _end) {
    
    
	size_t tau = 0;
	if (_begin < _end) {
    
    
		_Ty* _mid = _begin + (_end - _begin) / 2;
		tau += inversion_count(_begin, _mid);
		tau += inversion_count(_mid + 1, _end);
		tau += merge(_begin, _mid, _end);
	}
	return tau;
}

Guess you like

Origin blog.csdn.net/COFACTOR/article/details/109005737