分治算法---归并

1、排序数组

cpp 复制代码
class Solution 
{
    vector<int> tmp;
public:
    vector<int> sortArray(vector<int>& nums) 
    {
        tmp.resize(nums.size());
        mergeSort(nums,0,nums.size() - 1);
        return nums;
    }
    void mergeSort(vector<int>& nums, int left , int right)
    {
        if(left >= right) return;
        int mid = (left + right) >> 1;
        mergeSort(nums,left, mid);
        mergeSort(nums,mid + 1, right);
        int cur1 = left;
        int cur2 = mid+1;
        int i = 0;
        while((cur1 <= mid)&&(cur2 <= right))
        {
            if(nums[cur1]>nums[cur2])
            {
                tmp[i++] =  nums[cur2++];
            }
            else
            {
                tmp[i++] = nums[cur1++];
            }
        }
        while(cur1 <= mid)
        {
            tmp[i++] = nums[cur1++];
        }
          while(cur2 <= right)
        {
            tmp[i++] = nums[cur2++];
        }
        for(int i = left; i <= right;i++)
        {
            nums[i] = tmp[i - left];
        }
    }
};

2、数组中的逆序对

(2)解题思路

方法一:暴力解法,一个一个的寻找,虽然可以找到,但是会超时

方法二:归并

我们可以先找左边部分的逆序对,再找右半部分逆序对,最后再找一左一右的,如果我们可以找的途中还能排序,会使最后一步非常的简单 变成了 左半部分 -》左排序 -》右半部分 -》右排序 -》一左一右,这和归并算法的思想差不多

cpp 复制代码
class Solution 
{
    int tmp[50010];
public:
    int reversePairs(vector<int>& nums) 
    {
        return mergeSort(nums,0,nums.size() - 1);
    }
    int mergeSort(vector<int>& nums, int left, int right)
    {
        if(left>=right) return 0;
        int ret = 0;
        int mid = (left + right) >> 1;
        ret += mergeSort(nums,left,mid);
        ret += mergeSort(nums,mid+1,right);
        int i = 0;
        int cur1 = left;
        int cur2 = mid + 1;
        while(cur1 <=  mid && cur2 <= right)
        {
            if(nums[cur1] <= nums[cur2])
            {
                tmp[i++] = nums[cur1++];
            }
            else
            {
                ret +=  mid - cur1 + 1;
                tmp[i++] = nums[cur2++];
            }
        }
        while(cur1<=mid)
        {
            tmp[i++] = nums[cur1++];
        }
        while(cur2<=right)
        {
            tmp[i++] = nums[cur2++];
        }
        for(int j = left; j<=right; j++)
        {
            nums[j] = tmp[j -left];
        }
        return ret;
    }
};

3、计算右侧小于当前元素的个数

方法一:暴力解法

方法二:和上述的算法差不多,先算左边的数,在算右边的数,再算左右两边,右侧小于当前元素的个数

cpp 复制代码
class Solution 
{
    vector<int> tmp;
    vector<int> init;
    vector<int> ret;
    vector<int> tmpinit;
public:
    vector<int> countSmaller(vector<int>& nums) 
    {
        tmp.resize(size(nums));
        init.resize(size(nums));
        ret.resize(size(nums));
        tmpinit.resize(size(nums));
        for(int i = 0; i<nums.size();i++)
        {
            init[i] = i;
        }
         mergeSort(nums,0,nums.size() - 1);
         return ret;
    }
    void mergeSort(vector<int>& nums, int left , int right)
    {
        if(left>=right)
        {
            return ;
        }
        int mid = (left + right)>>1;
        mergeSort(nums,left,mid);
        mergeSort(nums, mid+1,right);
        int cur1 = left;
        int cur2 = mid+1;
        int i =0;
        while(cur1<=mid && cur2<=right)
        {
            if(nums[cur1]>nums[cur2])
            {
                ret[init[cur1]]+= right - cur2 +1;
                    tmp[i] = nums[cur1];
                tmpinit[i++] = init[cur1++];  
            }
            else
            {
                tmp[i] = nums[cur2];
                tmpinit[i++] = init[cur2++];  
            }
            
        }
        while(cur1<=mid)
        {
            tmp[i] = nums[cur1];
            tmpinit[i++] = init[cur1++];  
        }
         while(cur2<=right)
        {
            tmp[i] = nums[cur2];
            tmpinit[i++] = init[cur2++];  
        }
        for(int i = left ; i <= right; i++)
        {
            nums[i] = tmp[i-left];
            init[i] = tmpinit[i-left];
        }
    }
};

5、翻转对

cpp 复制代码
class Solution 
{
    vector<int> tmp;
public:
    int reversePairs(vector<int>& nums) 
    {
        tmp.resize(size(nums));
        return mergeSort(nums,0,nums.size()-1);
    }
    int mergeSort(vector<int>& nums, int left, int right)
    {
        int ret = 0;
        if(left>=right) return 0;
        int mid = (left + right) >> 1;
        ret += mergeSort(nums,left,mid);
        ret += mergeSort(nums,mid+1,right);
        int cur1 = left; 
        int cur2 = mid+1;
        int i = 0;
        while(cur1<=mid)
        {
            while(cur2<=right&&nums[cur2]>=nums[cur1]/2.0)
                  cur2++;
            if(cur2 > right)
                 break;
            ret += right - cur2 +1;
            cur1++;
        } 
        cur1 = left;
        cur2 = mid + 1;
        while(cur1 <=  mid && cur2 <= right)
        {
            if(nums[cur1] <= nums[cur2])
            {
                tmp[i++] = nums[cur2++];
            }
            else
            {

                tmp[i++] = nums[cur1++];
            }
        }
        while(cur1<=mid)
        {
            tmp[i++] = nums[cur1++];
        }
        while(cur2<=right)
        {
            tmp[i++] = nums[cur2++];
        }
        for(int j = left; j<=right; j++)
        {
            nums[j] = tmp[j -left];
        }
        return ret;
    }
};
相关推荐
小羊在睡觉4 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary5 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记5 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招
weixin_468466855 小时前
全局与局部注意力机制新手实战指南
人工智能·python·深度学习·算法·自然语言处理·transformer·注意力机制
_日拱一卒5 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
珂朵莉MM6 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--束搜索
人工智能·算法
Omics Pro6 小时前
首个!外源天然产物综合性代谢图谱
数据库·人工智能·算法·机器学习·r语言
voidmort7 小时前
3. 微调(Fine-tuning)与强化学习(RL)的核心思想
python·深度学习·算法
人道领域7 小时前
【LeetCode刷题日记】669.修剪二叉搜索树
开发语言·python·算法
QiLinkOS8 小时前
【从实验室到商业战场:发明专利如何重塑科技与企业的共生生态】
大数据·c语言·数据结构·c++·人工智能·单片机·算法