力扣刷题记录---归并排序

AcWing 787. 归并排序

力扣刷题记录---归并排序_第1张图片

归并排序代码模板如下:


/*
归并排序
时间O(nlogn),空间O(n)
*/

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] q=new int[n];
        for(int i=0;i<n;i++)q[i]=sc.nextInt();
        
        //进入归并排序
        mergeSort(q,0,n-1);
        
        //打印排序后的数组q
        for(int i=0;i<n;i++){
            if(i==n-1)System.out.print(q[i]);
            else System.out.print(q[i]+" ");
        }
        
    }
    //归并排序
    public static void mergeSort(int[] q,int l,int r){
        if(l>=r)return;
        int mid=l+r>>1;
        //以中间点划分归并区间,先进入递归
        mergeSort(q,l,mid);
        mergeSort(q,mid+1,r);
        
        //tmp数组暂存[l,r]区间内的排序后的元素
        int[] tmp=new int[r-l+1];
        
        //k用于tmp数组赋值,i作为左区间遍历指针,j作为右区间遍历指针
        int k=0,i=l,j=mid+1;
        
        //当左右区间当前遍历到的元素有一方更小时,将更小的赋值给tmp数组存储
        while(i<=mid&&j<=r){
            if(q[i]<q[j])tmp[k++]=q[i++];//同时tmp数组指针和赋值的那个区间指针前进1
            else tmp[k++]=q[j++];
        }
        //可能左右区间有一区间指针先到达右端点,要将剩下还没赋值的元素给tmp数组
        while(i<=mid)tmp[k++]=q[i++];
        while(j<=r)tmp[k++]=q[j++];
        
        //i用来遍历q数组[l,r]之间的元素进行赋值覆盖
        //j用来遍历tmp数组,把排序后的元素给q数组
        for(i=l,j=0;i<=r;i++,j++)q[i]=tmp[j];
        
    }
}

AcWing 788. 逆序对的数量

力扣刷题记录---归并排序_第2张图片

这题可以直接利用归并排序算法的模板,只需要在合并区间排序代码处,累加逆序对数量即可。

此外还需要注意的是n的最大值可能取到10 0000,所以最终逆序对最大可能是n(n-1)/2,超过int的表示范围,res需要定义为long型

代码如下:

import java.util.*;

class Main{
    public static void main(String[] args){
        Scanner sc =new Scanner(System.in);
        int n=sc.nextInt();
        int[] q=new int[n]; 
        for(int i=0;i<n;i++)q[i]=sc.nextInt();
        
        System.out.print(mergeSort(q,0,n-1));
    }
    
    //有long型返回值res
    public static long mergeSort(int[] q,int l,int r){
        
        //long型需要返回值,单个数不成对,返回0
        if(l>=r)return 0;
        int mid=l+r>>1;
        
        //最坏情况res=(n-1)+(n-2)+...+1=n(n-1)/2约等于10^10/2=5*10^9
        //超出int范围,所以要用long类型的res来接
        long res=mergeSort(q,l,mid)+mergeSort(q,mid+1,r);
        
        int[] tmp=new int[r-l+1];
        int k=0,i=l,j=mid+1;
        while(i<=mid&&j<=r){
            if(q[i]<=q[j])tmp[k++]=q[i++];
            else{//q[i]>q[j]时,q[i~mid]都会大于q[j]
                res+=mid-i+1;
                tmp[k++]=q[j++];
            }
        }
        
        while(i<=mid)tmp[k++]=q[i++];
        while(j<=r)tmp[k++]=q[j++];
        
        for(i=l,j=0;i<=r;i++,j++)q[i]=tmp[j];
        return res;
        
    }
}

你可能感兴趣的:(力扣刷题记录,数据结构与算法,Java,leetcode,java,算法)