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

}
相关推荐
qizayaoshuap7 分钟前
# [特殊字符] 密码生成器 — 鸿蒙ArkTS安全算法与密码强度评估系统
java·算法·安全·华为·harmonyos
良木林16 分钟前
滑动窗口 - LeetCode hot 100
javascript·算法·leetcode·双指针·滑动窗口
华玥作者19 分钟前
uniapp 万条数据不卡顿:我写了个虚拟列表组件 hy-list,原生支持瀑布流
数据结构·uni-app·list·vue3
2401_8414956420 分钟前
【数据结构】B*树
数据结构·c++·b树·算法·删除·插入·三分分裂
不如语冰1 小时前
AI大模型入门-模块导入import
数据结构·人工智能·pytorch·python
岑梓铭1 小时前
《考研408数据结构》第七章(7.1 查找:顺序查找、折半查找、分块查找)复习笔记
数据结构·笔记·考研·408·ds·查找
壹号用户2 小时前
c++入门之list了解及使用
数据结构·list
QXWZ_IA2 小时前
**电力登高作业高空失保实时监管:千寻智能安全带高挂低用监测方案**
人工智能·科技·算法·能源·智能硬件
来一碗刘肉面2 小时前
什么是双端队列
数据结构·链表
爱刷碗的苏泓舒2 小时前
FFRT:固定失败率比率检验、宽巷模糊度固定及 Ratio Test
算法·相位偏差·模糊度固定·ppp-ar·ffrt·ratio test·wlnl