归并排序递归法/非递归法;归并分治思想

归并排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class MergeSort {
    public static int MAXN = 100001;
    public static int[] arr = new int[MAXN];
    public static int[] help = new int[MAXN];

    public static int n;
    public static void main(String[] args) throws IOException{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StreamTokenizer in = new StreamTokenizer(br);
    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

        in.nextToken();
        n = (int)in.nval;
        for(int i = 0;i < n ;i++){
            in.nextToken();
            arr[i] = (int)in.nval;
        }
      //  mergeSort1(0,n-1);
        mergeSort2();
        
    for (int i = 0; i < n - 1; i++) {
			out.print(arr[i] + " ");
		}
        out.println(arr[n - 1]);
		out.flush();
		out.close();
		br.close();
    }
    // // 归并排序递归版
    // public static void mergeSort1(int l,int r){
    //     if(l == r){
    //         return;
    //     }
    //     int m = (l + r)/2;
    //     mergeSort1(l,m);
    //     mergeSort2(m+1,r);
    //     merge(l,m,r);
    // }
    
	// 归并排序非递归版
	// 时间复杂度O(n * logn)
	// 空间复杂度O(n)
      public static void mergeSort2(){
          //step 步长  步长每次增加一倍,步长<n继续
          //左部分 merge 右部分
          //l ... m m+1...   
          for(int l,m,r,step = 1; step < n; step = step*2){
              l = 0;
              while(l < n){
                  m = l + step -1;//左部分l...m 
                  if(m+1 >= n){//右部分开头>= n了。右部分没东西可以比较了,break
                      break;
                  }
                  //有右部分
                  //求右部分的右边界
                  r = Math.min(l+(step*2)-1,n-1);
                  merge(l,m,r);
                  l = r + 1 ;
              }
              
          }
    }
    

    //l...r
    //O(n)
    public static void merge(int l,int m,int r){
        int a = l;
        int b = m + 1;
        int i = l;
        while(a<=m && b<=r){
            help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];        
        }
// 左侧指针、右侧指针,必有一个越界、另一个不越界
        while(a<=m){
            help[i++] = arr[a++];
        }
        while(b<=r){
            help[i++] = arr[b++];
        }
        for(i = l;i<=r ;i++){
            arr[i] = help[i];
        }
    }
    
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.io.*;

public class Main {
    public static int MAXN = 100001;
    public static int[] arr = new int[MAXN];
    public static int n;
    public static int[] help = new int[MAXN];
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StreamTokenizer in = new StreamTokenizer(br);
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        while(in.nextToken() !=StreamTokenizer.TT_EOF){
            n = (int)in.nval;
            for(int i = 0;i < n;i++){
                in.nextToken();
                arr[i] = (int) in.nval;
            }
            out.println(smallSum(0,n-1));
        }
        out.flush();
        out.close();

    }
    public static long smallSum(int l,int r){
    //计算数组小数和==》 左部分数组小数和 +右部分数组小数和 + 左跨右的小数和
        if(l == r){
            return 0;
        }
        int m = l + (r-l)/2;//取(l,r)中点        
        return smallSum(l,m) + smallSum(m+1,r) +merge(l,m,r);
    }
    public static long merge(int l ,int m,int r){

        //
        long ans = 0;
        for(int i = l,j = m + 1,sum = 0;j <= r;j++){
            while(i <= m && arr[i]<=arr[j]){
                sum += arr[i++];
            }
            ans += sum;
        }
   
        //正常merge
        int a = l;
        int b = m + 1;
        int i = l;
        while(a<=m && b<= r){
            help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
        }
        while(a<=m){
            help[i++] = arr[a++];
        }
        while(b<=r){
            help[i++] = arr[b++];
        }
        for (i = l; i <= r; i++) {
			arr[i] = help[i];// 重要:排序好的部分拷贝回 arr
		}
        return ans;
    }
}

在这里插入图片描述

class Solution {
    //给定数组的长度不会超过50000。
   // public static int MAXN = 50001;
    //定义数组
 
    //定义归并排序所需要的辅助数组
    // public static int[] help = new int[MAXN];  

    public int reversePairs(int[] nums) {
       
       int[] help = new int[nums.length];
       return counts(nums,0,nums.length -1,help); 
    }
    public static int counts(int[] nums,int l, int r,int[] help){
         if(l == r){
            return 0;
        }
        //分成求左部分 + 右部分 + 左跨右
        //求中点m
        int m =  l + (r-l)/2 ;
        return counts(nums,l,m,help) + counts(nums,m + 1,r,help) + merge(nums,l,m,r,help);
    }
    
    public static int merge(int[] nums,int l,int m,int r,int[] help){
        //统计部分
        int ans = 0;
        for(int i = l, j = m + 1;i <= m; i++){
            while(j <= r && (long) nums[i] > (long) nums[j]*2){
                    j++;
            }
            ans += j - (m + 1);
        }

        //排序,加速统计
        //正常merge 归并排序
        int i = l;//定义i用来做辅助数组的指针
        int a = l;
        int b = m + 1;
        while(a <= m && b <= r){
            help[i++] = (nums[a] <= nums[b]) ? nums[a++] : nums[b++];
        }
        while(a <= m){
            help[i++] = nums[a++];
        }
        while(b <= r){
            help[i++] = nums[b++];
        }

        //把排好序的help数组复制到nums数组上去
        for(i = l;i <=r; i++){
            nums[i] = help[i];
        }

        return ans;
        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值