zoukankan      html  css  js  c++  java
  • 归并排序和归并排序应用(逆序对+小和)

    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; 
    	}
    };
    

      

  • 相关阅读:
    [BJOI2019] 光线
    C# 从零开始写 SharpDx 应用 笔刷
    BAT 脚本判断当前系统是 x86 还是 x64 系统
    BAT 脚本判断当前系统是 x86 还是 x64 系统
    win2d 通过 CanvasActiveLayer 画出透明度和裁剪
    win2d 通过 CanvasActiveLayer 画出透明度和裁剪
    PowerShell 拿到显卡信息
    PowerShell 拿到显卡信息
    win10 uwp 如何使用DataTemplate
    win10 uwp 如何使用DataTemplate
  • 原文地址:https://www.cnblogs.com/E-Dreamer-Blogs/p/12813761.html
Copyright © 2011-2022 走看看