当前位置: 首页 > news >正文

LeetCode:912归并排序,洛谷:ACM风格

文章目录

  • 归并排序
    • acm练习风格
    • 填函数练习风格

左程云算法学习笔记
详细的笔记都注释在代码上

归并排序

acm练习风格

测试链接

package class021;// 归并排序,acm练习风格
// 测试链接 : https://www.luogu.com.cn/problem/P1177
// 请同学们务必参考如下代码中关于输入、输出的处理
// 这是输入输出处理效率很高的写法
// 提交以下的code,提交时请把类名改成"Main",可以直接通过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 Code01_MergeSort {public static int MAXN = 100001;public static int[] arr = new int[MAXN];public static int[] help = new int[MAXN];//merge过程中的辅助数组//arr[]和help[]是全局静态static变量,所以所有的方法都不用放参数位置。参数位没有也能直接访问到。//使用全局静态变量能少些好多东西public static int n;//通过下面输入流的读入方式,n是arr的长度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;//并放入arr数组}// 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();}// 归并排序递归版// 假设l...r一共n个数// T(n) = 2 * T(n/2) + O(n)// a = 2, b = 2, c = 1// 根据master公式,时间复杂度O(n * logn)// 空间复杂度O(n) (需要额外的辅助数组)public static void mergeSort1(int l, int r) {if (l == r) {return;}int m = (l + r) / 2;mergeSort1(l, m);mergeSort1(m + 1, r);merge(l, m, r);}// 归并排序非递归版// 时间复杂度O(n * logn)// 空间复杂度O(n)public static void mergeSort2() {//从左到右,按步长=1,2,4……排完序以后再merge,不是递归,是从头一遍又一遍。//所以为什么不用传参数呢?数组是static,全局变量,那么直接方法里定义l,r,m即可// 一共发生O(logn)次for (int l, m, r, step = 1; step < n; step <<= 1) { //step是步长,这里的位运算表示每次都乘2,写成乘2也行,但是位运算比乘法运算快一点,其实秀技// 内部分组merge,时间复杂度O(n)l = 0;while (l < n) {m = l + step - 1;//0,,1,,2 这个步长是3	if (m + 1 >= n) {//发现右边界的初始越界就break,就不用merge了break;}//说明有右侧//接下来求右侧的右边界,左边界是m+1//左部分是的右边界是l+x-1,右部分和左部分是相等的长度,所以右部分的右边界是(拿l算为啥不拿m+1作为起始算?一样的,我的是思考的直接的方法(相比较多一步计算),这个是数学上简化代码上更优雅的方法)l + 2x - 1,即l + (step << 1) - 1。但是呢有可能数组没有这么长了,所以两者取min为右边界值r = Math.min(l + (step << 1) - 1, n - 1);merge(l, m, r);l = r + 1;}}}// l....r 一共有n个数// O(n)//merge不是递归方法 public static void merge(int l, int m, int r) {int i = l;//辅助数组help[]被填到了什么位置 int a = l;//a是左边有序数组的指针int b = m + 1;//b是右边有序数组的指针while (a <= m && b <= r) {//如果左右两侧都没有耗尽的话help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];//最经典的过程,谁小拷贝谁}// 左侧指针、右侧指针,必有一个越界、另一个不越界(所以下面两个while只会命中一个)//逻辑:哪边没耗尽就继续拷贝while (a <= m) {help[i++] = arr[a++];}while (b <= r) {help[i++] = arr[b++];}/*意义相同,下面是我写的,逻辑:哪边耗尽了就拷贝另一边while(a > m){help[i++] = arr[b++];}while (b > r){help[i++] = arr[a++];}*///至此,help[]的数字全部经过比较填写完成,限下面将其刷进原数组arr[]for (i = l; i <= r; i++) {arr[i] = help[i];}}}

在这里插入图片描述

填函数练习风格

测试链接

package class021;// 归并排序,填函数练习风格
// 测试链接 : https://leetcode.cn/problems/sort-an-array/public class Code02_MergeSort {public static int[] sortArray(int[] nums) {if (nums.length > 1) {// mergeSort1为递归方法// mergeSort2为非递归方法// 用哪个都可以// mergeSort1(nums);mergeSort2(nums);}return nums;}public static int MAXN = 50001;public static int[] help = new int[MAXN];// 归并排序递归版public static void mergeSort1(int[] arr) {sort(arr, 0, arr.length - 1);}public static void sort(int[] arr, int l, int r) {}// 归并排序非递归版public static void mergeSort2(int[] arr) {int n = arr.length;for (int l, m, r, step = 1; step < n; step <<= 1) {l = 0;while (l < n) {m = l + step - 1;if (m + 1 >= n) {break;}r = Math.min(l + (step << 1) - 1, n - 1);merge(arr, l, m, r);l = r + 1;}}}public static void merge(int[] arr, int l, int m, int r) {int i = l;int a = l;int b = m + 1;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];}}}

在这里插入图片描述

相关文章:

  • leetcode:42. 接雨水(秒变简单题)
  • 聊一聊 - 如何像开源项目一样,去设计一个组件
  • Linux系统编程-DAY12
  • Ubuntu下挂载NTFS格式磁盘
  • 延伸大疆AI能力:Coovally一键训练模型,直通无人机部署
  • SALOME源码分析: libBatch
  • [FX5U-PLC] 双重联锁正反转的继电接触控制线路
  • Matlab点云合并函数pcmerge全解析
  • 【算法篇】逐步理解动态规划模型5(子序列问题)
  • 《Playwright:微软的自动化测试工具详解》
  • MySQL学习之---索引
  • 关于类型断言的小细节
  • 【SAP MM SD FICO】销售视图和会计视图
  • 数据库——MongoDB
  • Java判断规则工具类
  • 【杂谈】-递归进化:人工智能的自我改进与监管挑战
  • 60天python训练计划----day50
  • 如何判断Cursor邮箱被封?
  • 《ZLMediaKit 全流程实战:从部署到 API 调用与前后端集成》
  • 【生物信息学】摇摆配对(Wobble Hypothesis)
  • 音乐培训如何做网站宣传/太原网站建设谁家好
  • 做网站视频博彩/网络优化大师app
  • 如何建设移动网站/深圳seo推广
  • 做网站业务员怎么查找客户/百度app怎么找人工客服
  • hotmail邮箱登录/seo推广代理
  • 白沙网站建设/产品网络营销推广方案