[Java 算法] 归并排序

练习一 : 排序数组(归并排序)

912. 排序数组 - 力扣(LeetCode)

java 复制代码
class Solution {
    int[] tmp;
    public int[] sortArray(int[] nums) {
        tmp = new int[nums.length];
        mergeSort(nums,0,nums.length-1);
        return nums;
    }
    public void mergeSort(int[] nums,int left,int right){
        if(left>=right) return;

        //划分区间
        int mid = (right+left)/2;

        //递归左右区间
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);

        //合并两个有序数组
        
        int cur1 = left,cur2 = mid+1,i = 0;
        while(cur1<=mid&&cur2<=right){
            tmp[i++] = (nums[cur1]<nums[cur2])?nums[cur1++]:nums[cur2++];
        }
        while(cur1<=mid){
            tmp[i++] = nums[cur1++];
        }
        while(cur2<=right){
            tmp[i++] = nums[cur2++];
        }
        //还原回nums数组
        for(int j = left;j<=right;j++){
            nums[j] = tmp[j-left];
        }
    }
}

算法原理 : 归并排序(分治)

1.划分区间 : left,mid , mid+1,right

2.递归左右区间

2.合并两个有序数组 : 双指针 cur1 = left,cur2 = mid+1

3.拷贝回 nums 数组 , 范围 left , right

练习二 : 交易逆序对的总数

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

java 复制代码
class Solution {
    int[] tmp;
    int count;
    public int reversePairs(int[] nums) {
        tmp = new int[nums.length];
        mergeSort(nums,0,nums.length-1);
        return count;
    }
    public void mergeSort(int[] nums,int left,int right){
        if(left>=right) return ;
        int mid = (right+left)/2;
        mergeSort(nums,left,mid);
        mergeSort(nums,mid+1,right);
        int cur1 = left,cur2 = mid+1 ,i = 0;
        while(cur1<=mid&&cur2<=right){
            if(nums[cur1]<=nums[cur2]){
                tmp[i++] = nums[cur1++];
                
            }else {//nums[cur1]>nums[cur2]
                count+=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];
        }
    }
}

算法原理 : 归并排序+统计

逆序对 : 5,4

分治 :

  • 分 : 把数组不断劈成两半 , 直到上下一个元素 (一个元素天然有序) ;
  • 治 : 把两个排好的小区间 , 合并为一个大的有序区间

在上一道归并排序的基础上添加了新的合并规则 : 合并规则(升序) :

  • numscur1<=numscur2 时不产生新的逆序对 , 只需要排序
  • numscur1>numscur2 时产生逆序对 , 由于是升序排序 , cur1 的右边也比 cur2 大 , 所以在 cur1~mid 区间的数都可以和 cur2 组成新的逆序对 , 注意不能统计已经遍历过的区间 , 容易重复计算

练习三 : 计算右侧小于当前元素的个数

315. 计算右侧小于当前元素的个数 - 力扣(LeetCode)

java 复制代码
class Solution {
    int[] Index;
    int[] tmpIndex;
    int[] tmpNums;
    int[] count;
    public List<Integer> countSmaller(int[] nums) {
        
        count = new int[nums.length];
        Index = new int[nums.length];//和指针同时移动,绑定下标
        for(int i = 0;i<nums.length;i++){
            Index[i] = i;
        }

        tmpIndex = new int[nums.length];//拷贝下标
        tmpNums = new int[nums.length];//拷贝数组
        megerSort(nums,0,nums.length-1);
        List<Integer> ret = new ArrayList<>();
        for(int num: count){
            ret.add(num);
        }
        return ret;
    }
    public void megerSort(int[] nums,int left,int right){
        if(left>=right) return ;
        int mid = (left+right)/2;
        megerSort(nums,left,mid);
        megerSort(nums,mid+1,right);
        int cur1 = left,cur2 = mid+1,i = 0;
        while(cur1<=mid&&cur2<=right){
            if(nums[cur1]<=nums[cur2]){
                tmpNums[i] = nums[cur2];
                tmpIndex[i] = Index[cur2];//同时排序 , 存储的原nums[cur2] 位置的元素
                i++;
                cur2++;
            }else{//nums[cur1]>nums[cur2]
                int index = Index[cur1];
                count[index] +=right-cur2+1;
                tmpNums[i] = nums[cur1];
                tmpIndex[i++] = Index[cur1++];
            }
        }
        while(cur1<=mid){
            tmpNums[i] = nums[cur1];
            tmpIndex[i++] = Index[cur1++];
        }
        
        while(cur2<=right){
            tmpNums[i] = nums[cur2];
            tmpIndex[i] = Index[cur2];
            i++;
            cur2++;
        }
        //拷贝
        for(int j = left;j<=right;j++){
            nums[j] = tmpNums[j-left];
            Index[j] = tmpIndex[j-left];
        }
    }

}
相关推荐
哭泣方源炼蛊8 小时前
并查集进阶 P1(带权并查集,并查集分类)
数据结构·c++·算法·二进制·带权并查集
牧羊人.3339 小时前
动手学深度学习 02 | 手写数字识别
图像处理·人工智能·深度学习·算法
武帝为此9 小时前
【InnoDB存储引擎介绍】
数据库·算法
shehuiyuelaiyuehao10 小时前
算法32,连续数组,前缀和+哈希表
算法·leetcode·职场和发展
五_谷_丰_登10 小时前
平衡二叉树(AVL)讲解二
数据结构·c++
程序员贺加贝10 小时前
报表大 IN 优化:一条 product_profile 超大 IN SQL 背后的报表任务治理
算法·性能优化
知无不研10 小时前
std::function在使用时遇到的问题
c++·算法·st·function
薛定e的猫咪11 小时前
(IEEE Transactions 2025)自适应元强化学习动态柔性作业车间调度框架
网络·人工智能·算法
码场老菜鸟11 小时前
C++ 指针的深度理解与应用
java·c++·算法
fpcc11 小时前
数据结构和算法—最短路径的算法
数据结构·算法