首页 > 其他分享 >分治---归并排序

分治---归并排序

时间:2024-10-19 10:23:07浏览次数:6  
标签:归并 nums int res 分治 mid --- import new

参考资料

水平有限,欢迎交流!
【如何优雅地排序——3分钟看懂【归并排序】的基本思想】

练习题

P1177 【模板】排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

关键步骤与应用

步骤

在归并过程中,主要包含两个关键步骤:

  1. 分割(Divide):将数组递归地分成两个或多个子数组。
  2. 合并(Merge):将两个或多个已排序的子数组合并成一个有序的大数组。

应用

可用于求逆序对的对数(力扣LCR 170)

归并排序

P1177 【模板】排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Main {
    static int N;
    static int[] arr;
    static int[] tmp;
    //分割
    static void MergeSort(int[] a, int l, int r) {
        if (l >= r) {
            return;
        }
        int mid = (l + r) >> 1;
        MergeSort(a, l, mid);
        MergeSort(a, mid + 1, r);
        merge(a, l, mid, r);
    }
    //合并
    static void merge(int[] a, int l, int mid, int r) {
        int i = l, j = mid + 1, k = 0;

        // 合并两个已排序的子数组
        while (i <= mid && j <= r) {
            if (a[i] <= a[j]) {
                tmp[k++] = a[i++];
            } else {
                tmp[k++] = a[j++];
            }
        }

        // 处理剩余的元素
        while (i <= mid) {
            tmp[k++] = a[i++];
        }

        // 将临时数组中的元素复制回原数组
        for (int x = 0; x < k; x++) {
            a[l+x] = tmp[x];
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
        N = Integer.parseInt(in.readLine());
        arr = new int[N];
        tmp = new int[N];
        String[]line = in.readLine().split(" ");
        for (int i = 0; i < N; i++) {
            arr[i] = Integer.parseInt(line[i]);
        }
        MergeSort(arr, 0, N - 1);
        for (int i : arr) {
            out.write(i + " ");
        }
        out.flush();
        in.close();
        out.close();
    }
}

求逆序对对数(仅考虑思路,不考虑消耗)

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

class Solution {
    int []tmp;
    int mergeSort(int []nums,int l,int r){
        if(l>=r)
            return 0;
        int cnt = 0;
        int mid = l +r >>1;
        cnt+=mergeSort(nums, l, mid);
        cnt+=mergeSort(nums, mid+1, r);
        int i = l,j = mid +1 ,k = 0;
        while(i<=mid&&j<=r){
            if(nums[i]<=nums[j]){
                tmp[k++] = nums[i++];
            }
            else{
                cnt+=(mid-i+1);
                tmp[k++] = nums[j++];
            }
        }
        while(i<=mid){
            tmp[k++] = nums[i++];
        }
        for(int x = 0;x<k;x++){
            nums[x+l] = tmp[x];
        }
        return cnt;
    }
    public int reversePairs(int[] record) {
        tmp = new int[record.length];
        return mergeSort(record, 0, record.length-1);
    }
}

3193. 统计逆序对的数目 - 力扣(LeetCode)
下面为暴力写法,过一半左右

import java.util.ArrayList;
import java.util.List;

class Solution {
    final int mod = 1000000007;
    List<List<Integer>> ans;
    int[] tmp;
    boolean[] vis;

    // 调整mergeSort方法以正确计算逆序对
    int mergeSortAndCount(List<Integer> cur, int l, int r) {
        if (l >= r) return 0;
        int mid = (l + r) >> 1;
        int count = 0;
        count += mergeSortAndCount(cur, l, mid);
        count += mergeSortAndCount(cur, mid + 1, r);
        count += mergeAndCount(cur, l, mid, r);
        return count;
    }

    int mergeAndCount(List<Integer> cur, int l, int mid, int r) {
        int i = l, j = mid + 1, k = 0;
        int count = 0;
        while (i <= mid && j <= r) {
            if (cur.get(i) <= cur.get(j)) {
                tmp[k++] = cur.get(i++);
            } else {
                tmp[k++] = cur.get(j++);
                count += (mid - i + 1);  // 确定逆序对的个数
            }
        }
        while (i <= mid) {
            tmp[k++] = cur.get(i++);
        }
        for (i = 0; i < k; i++) {
            cur.set(l + i, tmp[i]);
        }
        return count;
    }

    void dfs(int[] nums, List<Integer> res, int[][] requirements) {
        int len = nums.length;
        if (res.size() == len) {
            // 判断所有的要求是否都满足
            boolean isValid = true;
            for (int[] req : requirements) {
                int end = req[0];
                int cnt = req[1];
                List<Integer> sublist = new ArrayList<>(res.subList(0, end + 1));
                tmp = new int[sublist.size()];
                int inversionCount = mergeSortAndCount(sublist, 0, end);
                if (inversionCount != cnt) {
                    isValid = false;
                    break;
                }
            }
            if (isValid) {
                ans.add(new ArrayList<>(res)); // 只有满足所有要求时才添加到结果集
            }
            return;
        }
        for (int i = 0; i < len; i++) {
            if (!vis[i]) {
                vis[i] = true;
                res.add(nums[i]);
                dfs(nums, res, requirements);
                res.remove(res.size() - 1);
                vis[i] = false;
            }
        }
    }

    public int numberOfPermutations(int n, int[][] requirements) {
        ans = new ArrayList<>();
        int[] nums = new int[n];
        for (int j = 0; j < n; j++) {
            nums[j] = j;
        }
        vis = new boolean[n];
        dfs(nums, new ArrayList<>(), requirements);

        return ans.size() % mod;
    }
}

标签:归并,nums,int,res,分治,mid,---,import,new
From: https://www.cnblogs.com/qinLiCode/p/18475539

相关文章

  • XL6019芯龙180KHz 60V 5A开关电流升压/升降压型DC-DC转换器
    描述XL6019是一款专为升压、升降压设计的单片集成电路,可工作在DC5V到40V输入电压范围,低纹波,内置功率MOS。XL6019内置固定频率振荡器与频率补偿电路,简化了电路设计。PWM控制环路可以调节占空比从0~90%之间线性变化。内置过电流保护功能与EN脚逻辑电平关......
  • sql-labs靶场第十七关测试报告
    目录一、测试环境1、系统环境2、使用工具/软件二、测试目的三、操作过程1、寻找注入点2、注入数据库①寻找注入方法②爆库,查看数据库名称③爆表,查看security库的所有表④爆列,查看users表的所有列⑤成功获取用户名和密码信息3、sqlmap注入方法①爆库②爆表③爆......
  • sql-labs靶场第十六关测试报告
    目录一、测试环境1、系统环境2、使用工具/软件二、测试目的三、操作过程1、寻找注入点2、注入数据库①寻找注入方法②爆库,查看数据库名称③爆表,查看security库的所有表④爆列,查看users表的所有列⑤成功获取用户名和密码信息3、sqlmap注入方法①爆库②爆表③爆......
  • Java Spring详解 -- 看完超越99%的同行
    Spring的核心功能IOC(控制反转,依赖注入),AOP(面向切面的编程)IOC:我们在使用过程中不用关注于对象是怎么创建的,只用应用过去,sping自动帮我们完成注入,对象的创建,spring默认创建对象是单例,这样减少了频繁创建对象,让对象重复利用,所有的对象都是放在BeanFactory工厂的AOP:面向切面的编程,......
  • 启动service报错ORA-44317: database open read-only
    ADG(RAC)备库环境,srvctl添加service服务成功,启动service时报错ORA-44317:databaseopenread-only。这是预期行为,使用“srvctladdservice-d<db_name>-s<service_name>”创建服务时,将在OCR中创建和注册服务,但在使用“srvctlstartservice-d<db_name>-s<service_n......
  • 【数据结构】分治算法经典: 快速排序详解
    快速排序(Quicksort)是一种高效的排序算法,最早由TonyHoare在1960年提出。它采用了分治(DivideandConquer)策略,平均时间复杂度为O(nlog......
  • 门店收银系统源码-php+flutter+uniapp
     1.系统开发语言核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后台管理网站: HTML5+vue2.0+element-ui+css+js线下收银台(安卓/PC收银、安卓自助收银): Dart3框架:Flutter 3.19.6移动店务助手: uniapp线上商城: uniapp2.线下收银端线下收银端支持pc版(exe安装......
  • 一些有趣的数论题 - Updating
    P2568GCD给定正整数\(n\),求正整数数对\((x,y)\)的个数,该数对满足\(x\leqn,y\leqn\)且\(\gcd(x,y)\)是质数。首先我们可以枚举质数\(p\),求出\(\gcd(x,y)=p\)的数对个数然后对每一个质数求和即可。所以考虑如何求这个子问题。给定质数\(p\),求满足\(x\leqn,y\l......
  • 打开文件和文件夹工具类 - C#小函数类推荐
          此文记录的是打开文件和文件夹工具类。/***打开文件和文件夹工具类AustinLiu刘恒辉ProjectManagerandSoftwareDesignerE-Mail:[email protected]:http://lzhdim.cnblogs.comDate:2024-01-1515:18:00***/names......
  • python+uniapp微信小程序线上点餐管理信息系统java+nodejs-毕业设计
    前端开发框架:vue.js数据库mysql版本不限后端语言框架支持:1java(SSM/springboot)-idea/eclipse2.Nodejs+Vue.js-vscode3.python(flask/django)--pycharm/vscode4.php(thinkphp/laravel)-hbuilderx数据库工具:Navicat/SQLyog等都可以 随着科技的不断发展,移动互联网......