【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序

问题背景

班里有 m m m 位学生,共计划组织 n n n 场考试。给你一个下标从 0 0 0 开始、大小为 m × n m \times n m×n 的整数矩阵 s c o r e score score,其中每一行对应一位学生,而 s c o r e [ i ] [ j ] score[i][j] score[i][j] 表示第 i i i 位学生在第 j j j 场考试取得的分数。矩阵 s c o r e score score 包含的整数 互不相同
另给你一个整数 k k k。请你按第 k k k 场考试分数从高到低完成对这些学生(矩阵中的行)的排序。
返回排序后的矩阵。

数据约束

  • m = s c o r e . l e n g t h m = score.length m=score.length
  • n = s c o r e [ i ] . l e n g t h n = score[i].length n=score[i].length
  • 1 ≤ m , n ≤ 250 1 \le m, n \le 250 1m,n250
  • 1 ≤ s c o r e [ i ] [ j ] ≤ 105 1 \le score[i][j] \le 105 1score[i][j]105
  • s c o r e score score不同 的整数组成
  • 0 ≤ k < n 0 \le k \lt n 0k<n

解题过程

根据某个标准带着整个数组排序,可以当作模板记下来。
题目保证待排序的元素不重复,那就可以完全不考虑稳定性的问题。
写一下在其它算法中常用 O ( N l o g N ) O(NlogN) O(NlogN) 量级的简单做法,再把三种常用排序都实现一下当作练习好了。

具体实现

调用 API

class Solution {
    public int[][] sortTheStudents(int[][] score, int k) {
        Arrays.sort(score, (o1, o2) -> o2[k] - o1[k]);
        return score;
    }
}

归并排序 - 递归版

class Solution {
	// 二维数组最大长度为 250,开长为 300 的辅助数组就够了
    private static final int MAX_N = 300;
    private static final int[][] temp = new int[MAX_N][];
    private int k;

    public int[][] sortTheStudents(int[][] score, int k) {
        this.k = k;
        mergeSort(score, 0, score.length - 1);
        return score;
    }

    // 归并操作,入参改成二维数组
    private void merge(int[][] arr, int left, int mid, int right) {
        int index1 = left, index2 = mid + 1, index = left;
        while(index1 <= mid && index2 <= right) {
            // 除了收集元素的标准不一样,其它都可以不变
            temp[index++] = arr[index1][k] > arr[index2][k] ? arr[index1++] : arr[index2++];
        }
        while(index1 <= mid) {
            temp[index++] = arr[index1++];
        }
        while(index2 <= right) {
            temp[index++] = arr[index2++];
        }
        System.arraycopy(temp, left, arr, left, right - left + 1);
    }

    // 归并排序,入参改成二维数组
    private void mergeSort(int[][] arr, int left, int right) {
        if(left == right) {
            return;
        }
        int mid = left + ((right - left) >>> 1);
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }
}

归并排序 - 非递归版

class Solution {
	// 二维数组最大长度为 250,开长为 300 的辅助数组就够了
    private static final int MAX_N = 300;
    private static final int[][] temp = new int[MAX_N][];
    private int k;

    public int[][] sortTheStudents(int[][] score, int k) {
        this.k = k;
        mergeSort(score);
        return score;
    }

    // 归并操作,入参改成二维数组
    private void merge(int[][] arr, int left, int mid, int right) {
        int index1 = left, index2 = mid + 1, index = left;
        while(index1 <= mid && index2 <= right) {
            // 除了收集元素的标准不一样,其它都可以不变
            temp[index++] = arr[index1][k] > arr[index2][k] ? arr[index1++] : arr[index2++];
        }
        while(index1 <= mid) {
            temp[index++] = arr[index1++];
        }
        while(index2 <= right) {
            temp[index++] = arr[index2++];
        }
        System.arraycopy(temp, left, arr, left, right - left + 1);
    }

    // 归并排序,入参改成二维数组
    private void mergeSort(int[][] arr) {
        int n = arr.length;
        for(int left, mid, right, step = 1; step < n; step <<= 1) {
            left = 0;
            while(left < n) {
                mid = left + step - 1;
                if(mid >= n - 1) {
                    break;
                }
                right = Math.min(left + (step << 1) - 1, n - 1);
                merge(arr, left, mid, right);
                left = right + 1;
            }
        }
    }
}

随机快速排序

class Solution {
    private static int k;
    private static int first, last;

    public int[][] sortTheStudents(int[][] score, int k) {
        this.k = k;
        quickSort(score, 0, score.length - 1);
        return score;
    }

    // 交换操作,入参改成二维数组
    private void swap(int[][] arr, int i, int j) {
        int[] temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // 划分操作,入参改成二维数组
    private void partition(int[][] arr, int left, int right, int pivot) {
        first = left;
        last = right;
        int cur = left;
        while (cur <= last) {
            if (arr[cur][k] == pivot) {
                cur++;
            // 修改区域标准,较大的数往数组左侧交换
            } else if (arr[cur][k] > pivot) {
                swap(arr, first++, cur++);
            } else {
                swap(arr, cur, last--);
            }
        }
    }

    // 随机快排,入参改成二维数组
    private void quickSort(int[][] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int pivot = arr[left + (int) (Math.random() * (right - left + 1))][k];
        partition(arr, left, right, pivot);
        quickSort(arr, left, first - 1);
        quickSort(arr, last + 1, right);
    }
}

堆排序

class Solution {
    private int k;

    public int[][] sortTheStudents(int[][] score, int k) {
        this.k = k;
        heapSort(score);
        return score;
    }

    // 交换操作,入参改成二维数组
    private void swap(int[][] arr, int i, int j) {
        int[] temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    private void downAdjust(int[][] arr, int cur, int size) {
        int child = 2 * cur + 1;
        while (child < size) {
            // 修改确定修改目标的条件,用小根堆来完成排序,就能得到从大到小的结果
            int target = child + 1 < size && arr[child + 1][k] < arr[child][k] ? child + 1 : child;
            target = arr[target][k] < arr[cur][k] ? target : cur;
            if (target == cur) {
                break;
            }
            swap(arr, target, cur);
            cur = target;
            child = 2 * cur + 1;
        }
    }

    // 建堆操作,入参改成二维数组
    private void buildHeap(int[][] arr) {
        int n = arr.length;
        for (int i = n - 1; i >= 0; i--) {
            downAdjust(arr, i, n);
        }
    }

    // 堆排序,入参改成二维数组
    private void heapSort(int[][] arr) {
        buildHeap(arr);
        int size = arr.length;
        while (size > 0) {
            swap(arr, 0, --size);
            downAdjust(arr, 0, size);
        }
    }
}

总结梳理

Java 中的排序 API 的实现是 Tim Sort,大体上可以理解为在数据量较小的情况下使用 插入排序,通常使用归并排序。这里表现出来的效率不如直接实现的归并排序,猜想是因为整体数据量不是很大,在某些样例上被忽悠使用了效率不是那么高的算法。
归并排序 能够保证时间复杂度在 O ( N l o g N ) O(NlogN) O(NlogN) 这个量级的同时,算法本身是稳定的,是有必要自己实现排序算法时的首选,只需要考虑开辅助数组会不会影响效率。
快速排序 不仅需要额外的系统栈空间,还不稳定。它有时会成为面试时手撕算法的考题,需要好好掌握。
堆排序 是一种原地算法,但是不稳定,所以通常不是一个好的排序算法的选择。但是堆本身能够维护一系列元素中的最大值或者最小值,是一种非常好用的数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/940630.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中国人工智能学会技术白皮书

中国人工智能学会的技术白皮书具有多方面的重要作用&#xff0c;是极具权威性和价值的参考资料。 看看编委会和编写组的阵容&#xff0c;还是很让人觉得靠谱的 如何下载这份资料呢&#xff1f;下面跟着步骤来吧 步骤一&#xff1a;进入中国智能学会官网。百度搜索“中国智能学…

maui开发成生安卓apk,运行提示该应用与此设备的CPU不兼容

在生成.NET MAUI安卓应用时遇到“该应用与此设备的CPU不兼容”的问题&#xff0c;确保你的.NET MAUI应用支持的Android目标框架与设备CPU架构相匹配。例如&#xff0c;如果你的应用是为ARM64架构编译的&#xff0c;而你的设备是x86架构&#xff0c;就会出现不兼容的问题。 一、…

二叉树 -- 堆(详解)

目录 1、堆的概念及结构 2、堆的实现(附代码) 2.1、向下调整算法建堆 3、堆的应用(附代码) 3.1、堆排序 3.2、TOP-K问题 1、堆的概念及结构 如果有一个关键码的集合K { k0&#xff0c;k1 &#xff0c;k2 &#xff0c;…&#xff0c;k(n-1) }&#xff0c;把它的所有元素…

windows环境下pytorch安装踩坑

目录 1 前言2 安装Anaconda3 安装CUDA4 创建Python3.9环境5 安装Pytorch环境5.1 conda方式5.2 pip方式 6 验证是否安装成功7 注意事项7.1 no module named torch问题7.12 torch.cuda.is_available()返回False问题 8 最佳实践9 总结 1 前言 这两天由于要使用Genesis&#xff0c;…

Linux系统命令基础

Linux命令⾏ [pypylinux ~]$ 普通⽤户py&#xff0c;登陆后 [rootpylinux ~]# 超级⽤户root&#xff0c;登录后root代表当前登录的⽤户 分隔符pylinux 主机名~ 当前的登录的位置&#xff0c;此时是家⽬录# 超级⽤户身份提示符 $ 普通⽤户身份提示符操作系统⽬录分隔符 Linux目录…

PHP木马编写

一、最简单的一句话木马 <?php eval($_REQUEST[cmd]); ?> 1. <?php 和 ?> <?php 和 ?> 是 PHP 代码的开始和结束标记&#xff0c;表示 PHP 代码块的范围。 2. eval() eval() 是 PHP 中的一个内建函数&#xff0c;用来执行字符串类型的 PHP 代码。…

[Unity]【图形渲染】【游戏开发】Shader数学基础4-更多矢量运算

在计算机图形学和着色器编程中,矢量运算是核心的数学工具之一。矢量用于描述空间中的位置、方向、速度等各种物理量,并在图形变换、光照计算、纹理映射等方面起着至关重要的作用。本篇文章将详细讲解矢量和标量之间的乘法与除法、矢量的加法与减法、矢量的模与单位矢量、点积…

基于JSP动漫论坛的设计与实现【源码+文档】

目录 摘 要 Abstract 1. 绪论 1.1 课题背景 1.2 国内外现状 1.3 动漫论坛系统特点 1.4 发展前景 1.5 所做的主要工作 2. 可行性分析及需求分析 2.1 可行性分析 2.1.1 经济可行性 2.1.2 技术可行性 2.1.3 运行可行性 2.2 需求分析 2.2.1 功能需求 …

VCU--新能源汽车VCU电控开发

课程目标 信号采集的原理 使用simulink处理信号 做一个MIL仿真测试 零、参考 构建Simulink模型——CAN通信 | chans Bloggerrrrr基于Simulink实现CAN报文解析(unpack)与打包(pack)任务_RichardsZ_-开放原子开发者工作坊 一、功能概述 1.硬线信号 定义&#xff1a;通过物…

nodejs搭配express网站开发后端接口设计需要注意事项

nodejs搭配express网站开发后端接口设计需要注意事项&#xff01;为了回避一些常见的误区&#xff0c;今天和大家汇总一下&#xff0c;最近我遇到的一些错误信息&#xff0c;虽然都是小问题&#xff0c;但是还是需要分享一下&#xff0c;以免大家再次犯错。 1&#xff1a;第一个…

【时间之外】IT人求职和创业应知【71】-专利费

目录 2025 ICT产业趋势年会召开&#xff0c;2024年度ICT十大新闻重磅揭晓 海纳致远数字科技申请定制化插件驱动的数据分析专利 阿波罗智联取得语音数据的处理方法、装置、设备和存储介质专利 心勿贪&#xff0c;贵知足。 感谢所有打开这个页面的朋友。人生不如意&#xff0…

问题小记-达梦数据库报错“字符串转换出错”处理

最近遇到一个达梦数据库报错“-6111: 字符串转换出错”的问题&#xff0c;这个问题主要是涉及到一条sql语句的执行&#xff0c;在此分享下这个报错的处理过程。 问题表现为&#xff1a;一样的表结构和数据&#xff0c;执行相同的SQL&#xff0c;在Oracle数据库中执行正常&…

数据结构——队列的模拟实现

大家好&#xff0c;上一篇博客我带领大家进行了数据结构当中的栈的模拟实现 今天我将带领大家实现一个新的数据结构————队列 一&#xff1a;队列简介 首先来认识一下队列&#xff1a; 队列就像我们上学时的排队一样&#xff0c;有一个队头也有一个队尾。 有人入队的话就…

前端面试汇总(不定时更新)

目录 HTML & CSS1. XML、HTML、XHTML 有什么区别&#xff1f;⭐2. XML和JSON的区别&#xff1f;3. 是否了解W3C的规范&#xff1f;⭐4. 什么是语义化标签&#xff1f;⭐⭐5. 行内元素和块级元素的区别&#xff1f;⭐6. 行内元素和块级元素的转换&#xff1f;⭐7. 常用的块级…

在UE5中调用ImGui图形界面库

ImGui是一个小巧灵活、简洁美观的图形界面库 首先我们直接参考Github https://github.com/SLSNe/Unreal5-ImGui 把项目下载下来后 打开项目目录或者引擎目录 项目根目录/Plugins/ImGui/ 或 UE5引擎根目录/Engine/Plugins/ 如果没有Plugins文件夹就新建一个 把项目放里面…

数据结构与算法:稀疏数组

前言 此文以整型元素的二维数组为例&#xff0c;阐述稀疏数组的思想。其他类型或许有更适合压缩算法或者其他结构的稀疏数组&#xff0c;此文暂不扩展。 稀疏数组的定义 在一个二维数据数组里&#xff0c;由于大量的元素的值为同一个值&#xff0c;比如 0或者其他已知的默认值…

【蓝桥杯】43699-四平方和

四平方和 题目描述 四平方和定理&#xff0c;又称为拉格朗日定理&#xff1a; 每个正整数都可以表示为至多 4 个正整数的平方和。如果把 0 包括进去&#xff0c;就正好可以表示为 4 个数的平方和。 比如&#xff1a; 502021222 712121222; 对于一个给定的正整数&#xff0c;可…

ECharts散点图-SymbolShapeMorph,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…

会话控制(cookie、session 和 token)

1. 介绍 所谓会话控制就是 对会话进行控制HTTP 是一种无状态的协议&#xff0c;它没有办法区分多次的请求是否来自于同一个客户端&#xff0c; 无法区分用户&#xff0c;而产品中又大量存在的这样的需求&#xff0c;所以我们需要通过 会话控制 来解决该问题。 常见的会话控制…

「九」HarmonyOS 5 端云一体化实战项目——「M.U.」应用云侧开发云数据库

1 立意背景 M. 代表 “我”&#xff0c;U. 代表 “你”&#xff0c;这是一款用于记录情侣从相识、相知、相恋、见家长、订婚直至结婚等各个阶段美好记忆留存的应用程序。它旨在为情侣们提供一个专属的空间&#xff0c;让他们能够将一路走来的点点滴滴&#xff0c;如初次相遇时…