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

      

  • 相关阅读:
    python--tkinter桌面编程开发--记事本
    Python--面向对象编程
    Python--面向对象编程--时钟实例开发
    Python学习笔记--2--面向对象编程
    Python学习笔记--1
    epoll聊天室的实现
    操作系统--虚拟存储器
    操作系统--存储器管理
    操作系统--分页存储管理中逻辑地址转换为物理地址
    操作系统--处理机调度与死锁
  • 原文地址:https://www.cnblogs.com/E-Dreamer-Blogs/p/12813761.html
Copyright © 2011-2022 走看看