【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 int k;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;}public static int first, 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);}// 划分操作,入参改成二维数组public 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--);}}}
}

堆排序

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) 这个量级的同时,算法本身是稳定的,是有必要自己实现排序算法时的首选,只需要考虑开辅助数组会不会影响效率。
快速排序 不仅需要额外的系统栈空间,还不稳定。它有时会成为面试时手撕算法的考题,需要好好掌握。
堆排序 是一种原地算法,但是不稳定,所以通常不是一个好的排序算法的选择。但是堆本身能够维护一系列元素中的最大值或者最小值,是一种非常好用的数据结构。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React系列(八)——React进阶知识点拓展

前言 在之前的学习中&#xff0c;我们已经知道了React组件的定义和使用&#xff0c;路由配置&#xff0c;组件通信等其他方法的React知识点&#xff0c;那么本篇文章将针对React的一些进阶知识点以及React16.8之后的一些新特性进行讲解。希望对各位有所帮助。 一、setState &am…

PCIe_Host驱动分析_地址映射

往期内容 本文章相关专栏往期内容&#xff0c;PCI/PCIe子系统专栏&#xff1a; 嵌入式系统的内存访问和总线通信机制解析、PCI/PCIe引入 深入解析非桥PCI设备的访问和配置方法 PCI桥设备的访问方法、软件角度讲解PCIe设备的硬件结构 深入解析PCIe设备事务层与配置过程 PCIe的三…

【阅读记录-章节6】Build a Large Language Model (From Scratch)

文章目录 6. Fine-tuning for classification6.1 Different categories of fine-tuning6.2 Preparing the dataset第一步&#xff1a;下载并解压数据集第二步&#xff1a;检查类别标签分布第三步&#xff1a;创建平衡数据集第四步&#xff1a;数据集拆分 6.3 Creating data loa…

ip_output函数

ip_output函数是Linux内核(特别是网络子系统)中用于发送IPv4数据包的核心函数。以下是一个示例实现,并附上详细的中文讲解: int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb) {struct iphdr *iph; /* 构建IP头部 */iph = ip_hdr(skb);/* 设置服务…

梳理你的思路(从OOP到架构设计)_简介设计模式

目录 1、 模式(Pattern) 是较大的结构​编辑 2、 结构形式愈大 通用性愈小​编辑 3、 从EIT造形 组合出设计模式 1、 模式(Pattern) 是较大的结构 组合与创新 達芬奇說&#xff1a;簡單是複雜的終極形式 (Simplicity is the ultimate form of sophistication) —Leonardo d…

用SparkSQL和PySpark完成按时间字段顺序将字符串字段中的值组合在一起分组显示

用SparkSQL和PySpark完成以下数据转换。 源数据&#xff1a; userid,page_name,visit_time 1,A,2021-2-1 2,B,2024-1-1 1,C,2020-5-4 2,D,2028-9-1 目的数据&#xff1a; user_id,page_name_path 1,C->A 2,B->D PySpark&#xff1a; from pyspark.sql import SparkSes…

【libuv】Fargo信令2:【深入】client为什么收不到服务端响应的ack消息

客户端处理server的ack回复,判断链接连接建立 【Fargo】28:字节序列【libuv】Fargo信令1:client发connect消息给到server客户端启动后理解监听read消息 但是,这个代码似乎没有触发ack消息的接收: // 客户端初始化 void start_client(uv_loop_t

硬盘dma读写过程

pci初始化时&#xff0c;遍历pci上的设置&#xff0c;如果BaseClassCode1&#xff0c;则为大容量存储控制器&#xff0c;包括硬盘控制器、固态硬盘控制器、光盘驱动控制器、RAID控制器等。 BaseAdder4为DMA控制器基地址&#xff0c;包含两个控制器&#xff0c;主控制器&#x…

Python-基于Pygame的小游戏(贪吃蛇)(一)

前言:贪吃蛇是一款经典的电子游戏&#xff0c;最早可以追溯到1976年的街机游戏Blockade。随着诺基亚手机的普及&#xff0c;贪吃蛇游戏在1990年代变得广为人知。它是一款休闲益智类游戏&#xff0c;适合所有年龄段的玩家&#xff0c;其最初为单机模式&#xff0c;后来随着技术发…

使用k6进行MongoDB负载测试

1.安装环境 安装xk6-mongo扩展 ./xk6 build --with github.com/itsparser/xk6-mongo 2.安装MongoDB 参考Docker安装MongoDB服务-CSDN博客 连接成功后新建test数据库和sample集合 3.编写脚本 test_mongo.js import xk6_mongo from k6/x/mongo;const client xk6_mongo.new…

solon 集成 activemq-client (sdk)

原始状态的 activemq-client sdk 集成非常方便&#xff0c;也更适合定制。就是有些同学&#xff0c;可能对原始接口会比较陌生&#xff0c;会希望有个具体的示例。 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-client&l…

2024 年最新前端ES-Module模块化、webpack打包工具详细教程(更新中)

模块化概述 什么是模块&#xff1f;模块是一个封装了特定功能的代码块&#xff0c;可以独立开发、测试和维护。模块通过导出&#xff08;export&#xff09;和导入&#xff08;import&#xff09;与其他模块通信&#xff0c;保持内部细节的封装。 前端 JavaScript 模块化是指…

uni-app商品搜索页面

目录 一:功能概述 二:功能实现 一:功能概述 商品搜索页面,可以根据商品品牌,商品分类,商品价格等信息实现商品搜索和列表展示。 二:功能实现 1:商品搜索数据 <view class="search-map padding-main bg-base"> <view class…

最小堆及添加元素操作

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 最小堆及添加元素操作 [太阳]选择题 以下代码执行的结果为&#xff1f; import heapq heap [] heapq.heappush(heap, 5) heapq.heappush(heap, 3) heapq.heappush(heap, 2) heapq.…

10. 考勤信息

题目描述 公司用一个字符串来表示员工的出勤信息 absent:缺勤late: 迟到leaveearly: 早退present: 正常上班 现需根据员工出勤信息&#xff0c;判断本次是否能获得出勤奖&#xff0c;能获得出勤奖的条件如下: 缺勤不超过一次&#xff0c;没有连续的迟到/早退:任意连续7次考勤&a…

【计算机网络】期末考试预习复习|中

作业讲解 转发器、网桥、路由器和网关(4-6) 作为中间设备&#xff0c;转发器、网桥、路由器和网关有何区别&#xff1f; (1) 物理层使用的中间设备叫做转发器(repeater)。 (2) 数据链路层使用的中间设备叫做网桥或桥接器(bridge)。 (3) 网络层使用的中间设备叫做路…

前端工程化-Vue脚手架安装

在现代前端开发中&#xff0c;Vue.js已成为一个流行的框架&#xff0c;而Vue CLI&#xff08;脚手架&#xff09;则为开发者提供了一个方便的工具&#xff0c;用于快速创建和管理Vue项目。本文将详细介绍如何安装Vue脚手架&#xff0c;创建新项目以及常见问题的解决方法。 什么…

利用爬虫获取的数据能否用于商业分析?

在数字化时代&#xff0c;数据已成为企业获取竞争优势的关键资源。网络爬虫作为一种数据收集工具&#xff0c;能够从互联网上抓取大量数据&#xff0c;这些数据在商业分析中扮演着重要角色。然而&#xff0c;使用爬虫技术获取的数据是否合法、能否用于商业分析&#xff0c;是许…

罗德与施瓦茨ZN-Z129E网络分析仪校准套件具体参数

罗德与施瓦茨ZN-Z129E网络校准件ZN-Z129E网络分析仪校准套件 1&#xff0c;频率范围从9kHz到4GHz&#xff08;ZNB4&#xff09;,8.5GHz(ZNB8)&#xff0c;20GHz(ZNB20)&#xff0c;40GHz(ZNB40) 2&#xff0c;动态范围宽&#xff0c;高达140 dB 3&#xff0c;扫描时间短达4ms…

如何为IntelliJ IDEA配置JVM参数

在使用IntelliJ IDEA进行Java开发时&#xff0c;合理配置JVM参数对于优化项目性能和资源管理至关重要。IntelliJ IDEA提供了两种方便的方式来设置JVM参数&#xff0c;以确保你的应用程序能够在最佳状态下运行。本文将详细介绍这两种方法&#xff1a;通过工具栏编辑配置和通过服…