归并排序和归并排序应用(逆序对+小和)

PS:归并排序是一个套路迭代的过程,归并排序与数组中的逆序对和最小和问题三个基本上一样,只要理解了归并排序过程,其余两个过程自然可以理解。 直接上代码。 

归并排序过程

class Solution {
public:
        void mergeSort(vector<int> &arr) {
               if (arr.size() == 0 || arr.size() < 2) return;
               SortProcess(arr, 0, arr.size()-1);
        }
        //归并排序主体过程
        void SortProcess(vector<int> &arr, int l, int r) { 
               if (r == l) return; // 递归停止
               int mid = l + (r - l)/2;
               SortProcess(arr, l, mid);
               SortProcess(arr, mid + 1, r);
               merge(arr, l, mid, r);
        }
        // 合并过程
        void merge(vector<int> &arr, int l, int mid, int r) { // 这里需要 & ,不然会答案错误
               vector<int> helper(r - l + 1); // 辅助数组用来存放排序后的数组
               int i = 0;
               // 两个指针
               int p1 = l;
               int p2 = mid + 1;
               while (p1 <= mid && p2 <= r) {
                       if (arr[p1] < arr[p2]) {
                              helper[i++] = arr[p1++];
                       }
                       else {
                              helper[i++] = arr[p2++];
                       }
               }
               while (p1 <= mid) {// 注意这里可以等于
                       helper[i++] = arr[p1++];
               }
               while (p2 <= r) {
                       helper[i++] = arr[p2++];
               }
               // 将辅助数组元素位置拷贝会arr
               for (int i = 0; i < helper.size(); i++) {
                       arr[l + i] = helper[i];
               }
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

数组中的逆序对

class Solution2 {
public:
    int cnt = 0;
    int reversePairs(vector<int> data) {
        int n = data.size();
        if (n != 0)
        {
            mergesort(data, 0, n - 1);   //调用归并排序的分解函数
        }
        return cnt;
    }
    
    void mergesort(vector<int>& data, int start, int end)   //分解
    {
        if (start < end )  // 递归终止条件
        {
            int mid = (start + end) >> 1;
            mergesort(data, start, mid );
            mergesort(data, mid+1,end);
            merge(data, start, mid, end); //调用归并排序的合并排序函数
        }
    }
    
    void merge(vector<int>& data, int start, int mid, int end)
    {
        vector<int> tmp(end-start+1);      //tmp临时变量用来存储当前[start,end]段排序后的结果,然后再赋值给data
        // 注意:一定要写大小,不然使用下标会出错
        int i = start, j = mid + 1;         //采用的是引用传递,所以修改的是原数组
        int index = 0;
        while (i <= mid&&j <= end)
        {
            if (data[i] > data[j])         
            {  // 此时产生逆序对
                cnt = (cnt + mid - i + 1);   // 有些题目需要取余数
                tmp[index++] = data[j++];  // 这里也可以用tmp.push_back(data[j++] 
            }
            else
                tmp[index++] = data[i++];
        }                                   //tmp就是存data(start,end)区间内从小到大的存储起来
        while (i <= mid) {
            tmp[index++] = data[i++];
        }
        while (j <=end) {
            tmp[index++] = data[j++];
        }
        for (int i = 0; i < tmp.size(); ++i)
        {
            data[start + i] = tmp[i];
        }
    }
};

最小和问题

class Solution3 {  
public:
	void Small_sum(vector<int> nums) {
		if (nums.size() == 0) return;
		sort_process(nums, 0, nums.size() - 1);
	}
	int  sort_process(vector<int> &nums, int l, int r) {
		// 递归停止
		if (r == l) return;
		int mid = l + (r - l) / 2;
		return sort_process(nums, mid + 1, r)+
			sort_process(nums, l, mid)+ merge(nums, l, mid, r);

	}
	int  merge(vector<int> &arr, int l, int mid, int r) {
		vector<int> helper(r - l + 1);  // 辅助数组
		int res = 0;  // 产生小和数目
		int i = 0;
		int p1 = l;
		int p2 = mid + 1;
		while (p1 < mid && p2 <= r) {
			if (arr[p1] < arr[p2]) {
				res += (r - p2 + 1) * arr[p1];
				helper[i++] = arr[p1++];
			}
			else {
				helper[i++] = arr[p2++];
			}
		}
		while (p1 <= mid) {
			helper[i++] = arr[p1++];
		}
		while (p2 <= r) {
			helper[i++] = arr[p2++];
		}
		// 将辅助数组元素位置拷贝会arr
		for (int i = 0; i < helper.size(); i++) {
			arr[l + i] = helper[i];
		}
		return res; 
	}
};

  

原文地址:https://www.cnblogs.com/E-Dreamer-Blogs/p/12813761.html