从归并排序引申到排序链表-图解

从归并排序引申到排序链表

文章目录

    • 从归并排序引申到排序链表
      • 归并排序
        • 递归版
        • 非递归版
      • 排序链表
        • 递归版
        • 非递归版

归并排序

递归版

在这里插入图片描述

    //合并排序
    public static void mergeSort(int[] nums) {
        mergeSortHelper(0, nums.length, nums); //没有-1
    }

    private static void mergeSortHelper(int low, int high, int[] nums) {
        if (low >= high || high - low == 1) { //区间为空区间或只有一个元素,不用排序
            return;
        }
        int mid = (low+high)/2;
        //递归对子区间归并排序
        mergeSortHelper(low, mid, nums);//[low, mid)
        mergeSortHelper(mid, high, nums);//[mid, high)
        merge(low, mid, high, nums);
    }

    //合并两个有序数组
    private static void merge(int low, int mid, int high, int[] nums) {
        int i = low;
        int j = mid;
        int t = high - low;
        int[] extra = new int[t];
        int k = 0;
        while (i < mid && j < high) {
            //保证稳定性
            if (nums[i] <= nums[j]) {
                extra[k++] = nums[i++];
            } else {
                extra[k++] = nums[j++];
            }
        }

        while (i < mid) {
            extra[k++] = nums[i++];
        }
        while (j < high) {
            extra[k++] = nums[j++];
        }

        for (int x = 0; x < t; x++) {
            
            nums[low+x] = extra[x];
        }
    }
非递归版

在这里插入图片描述

    //非递归版本
    public static void mergeSort2(int[] nums) {
        //1.将数组拆分为若干个长度为size的子数组
        for (int size = 1; size < nums.length; size *= 2) {
            //1.1循环,开始对子数组操作
            for (int i = 0; i < nums.length; i += 2*size) {
                //1.1.1得到子数组n1
                int n1 = i;
                //1.1.2得到子数组n2
                int n2 = i+size;
                if (n2 > nums.length) {
                    continue;
                }
                //1.1.3去掉n1 n2的内容之后原数组剩余的内容用next保存
                int next = n2 + size;
                if (next > nums.length) {
                    next = nums.length;
                }
                merge(nums, n1, n2, next);
            }
        }
    }

排序链表

OJ链接

递归版

在这里插入图片描述

public class $148 {
    //法一:使用递归,自顶向下归并排序
    public ListNode sortList(ListNode head) {
        return sortList(head, null);
    }

    private ListNode sortList(ListNode head, ListNode tail) {
        //链表为空
        if (head == null) {
            return head;
        }

        //链表只有一个节点
        if (head.next == tail) {
            head.next = null;
            return head;
        }

        //1.找到链表的中间节点(返回第二个中间节点)
        ListNode fast = head;
        ListNode slow = head;
        while (fast != tail && fast.next != tail) { //tail
            fast = fast.next.next;
            slow = slow.next;
        }

        //2.对两个子链表分别排序
        ListNode mid = slow;
        ListNode list1 = sortList(head, mid);
        ListNode list2 = sortList(mid, tail);

        //3.合并两个已排序子链表
        ListNode sorted = merge(list1, list2);
        return sorted;
    }

    private ListNode merge(ListNode list1, ListNode list2) {
        ListNode mergedHead = new ListNode(0);
        ListNode temp = mergedHead;
        ListNode temp1 = list1;
        ListNode temp2 = list2;

        while (temp1 != null && temp2 != null) {
            if (temp1.val < temp2.val) {
                temp.next = temp1;
                temp1 = temp1.next;
            } else {
                temp.next = temp2;
                temp2 = temp2.next;
            }
            temp = temp.next;
        }

        if (temp1 != null) {
            temp.next = temp1;
        } else {
            temp.next = temp2;
        }

        return mergedHead.next;
    }
}
非递归版

在这里插入图片描述

public class $148 {
    //法二:自底向上归并排序
    public ListNode sortList2(ListNode head) {
        //1.得到链表长度
        int len = 0;
        ListNode node = head;
        while (node != null) {
            node = node.next;
            len++;
        }

        //2.引入虚拟头结点,连接head
        ListNode dummyHead = new ListNode(-1);
        dummyHead.next = head;

        //3将链表拆分为若干个长度为size的子链表
        for (int size = 1; size < len; size *= 2) {
            //3.1prev,cur
            ListNode prev = dummyHead;
            ListNode cur = dummyHead.next;

            //3.2循环,开始对子链表进行操作
            while (cur != null) {
                //3.2.1得到长度为size的链表l1
                ListNode l1 = cur;
                for (int i = 1; i < size && cur.next != null; i++) {
                    cur = cur.next;
                }

                //3.2.2得到长度为size的链表l2,并切断两个链表的连接
                ListNode l2 = cur.next;
                cur.next = null;
                cur = l2;
                for (int i = 1; i < size && cur != null && cur.next != null; i++) {
                    cur = cur.next;
                }

                //3.2.3去掉链表1链表2之后原链表剩余的内容用next保存
                //同时切断next与两个链表的连接
                ListNode next = null;
                if (cur != null) {
                    next = cur.next;
                    cur.next = null;
                }


                //3.2.4合并两个排序链表得到merged
                ListNode merged = merge(l1, l2);

                //3.2.5prev连上merged,将prev指向merged的末尾
                prev.next = merged;
                while (prev.next != null) {
                    prev = prev.next;
                }

                //3.2.6cur指向next
                cur = next;
            }
        }
        return dummyHead.next;
    }
  
      private ListNode merge(ListNode list1, ListNode list2) {
        ListNode mergedHead = new ListNode(0);
        ListNode temp = mergedHead;
        ListNode temp1 = list1;
        ListNode temp2 = list2;

        while (temp1 != null && temp2 != null) {
            if (temp1.val < temp2.val) {
                temp.next = temp1;
                temp1 = temp1.next;
            } else {
                temp.next = temp2;
                temp2 = temp2.next;
            }
            temp = temp.next;
        }

        if (temp1 != null) {
            temp.next = temp1;
        } else {
            temp.next = temp2;
        }

        return mergedHead.next;
    }
}

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

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

相关文章

python 使用 pip 安装第三方库 导入不成功

本文是什么意思呢&#xff1f; 就是你需要使用一些库安装老师或者网上说的 通过pip 安装下载了第三方库&#xff0c;但是使用 import xxx from xxx import xx &#xff0c;pycharm ide 导入的下面还有红色波浪线&#xff0c;导入不成功。 这是什么原因&#xff1f; 这是pyc…

飞天使-k8s知识点5-kubernetes基础名词扫盲

文章目录 deploymentspodNodeserviceskubectl 实现应用伸缩kubectl 实现滚动更新kubernetes架构 deployments 中文文档 http://docs.kubernetes.org.cn/251.htmldeployment是用来创建和更新应用的&#xff0c;master 会负责将创建好的应用实例调度到集群中的各个节点 应用实例…

Qt 开源项目

Qt 开源项目 Omniverse View链接技术介绍 QuickQanava链接技术介绍QField链接技术介绍 AtomicDEX链接技术介绍 Status-desktop链接技术介绍 Librum链接技术介绍 A Simple Cross-Platform ReaderQPrompt链接技术介绍 GCompris链接技术介绍 Scrite链接技术介绍 QSkinny链接技术介…

力扣思维题——寻找重复数

题目链接&#xff1a;https://leetcode.cn/problems/find-the-duplicate-number/description/?envTypestudy-plan-v2&envIdtop-100-liked 这题的思维难度较大。一种是利用双指针法进行计算环的起点&#xff0c;这种方法在面试里很难说清楚&#xff0c;也很难想到。大致做…

银河麒麟v10 二进制安装包 安装mysql 8.35

银河麒麟v10 二进制安装包 安装mysql 8.35 1、卸载mariadb2、下载Mysql安装包3、安装Mysql 8.353.1、安装依赖包3.2、安装Mysql3.3、安装后配置 1、卸载mariadb 由于银河麒麟v10系统默认安装了mariadb 会与Mysql相冲突&#xff0c;因此首先需要卸载系统自带的mariadb 查看系统…

Quartz.NET 事件监听器

1、调度器监听器 调度器本身收到的一些事件通知&#xff0c;接口ISchedulerListener&#xff0c;如作业的添加、删除、停止、挂起等事件通知&#xff0c;调度器的启动、关闭、出错等事件通知&#xff0c;触发器的暂停、挂起等事件通知&#xff0c;接口部分定义如下&#xff1a…

面试题:JVM 对锁都进行了哪些优化?

文章目录 锁优化自旋锁和自适应自旋锁消除锁粗化逃逸分析方法逃逸线程逃逸通过逃逸分析&#xff0c;编译器对代码的优化 锁优化 jvm 在加锁的过程中&#xff0c;会采用自旋、自适应、锁消除、锁粗化等优化手段来提升代码执行效率。 自旋锁和自适应自旋 现在大多的处理器都是…

C++入门-【13-C++ 多维数组】

C 多维数组 C 支持多维数组。多维数组声明的一般形式如下&#xff1a; type name[size1][size2]...[sizeN]; 例如&#xff0c;下面的声明创建了一个三维 5 . 10 . 4 整型数组&#xff1a; int threedim[5][10][4]; 二维数组 多维数组最简单的形式是二维数组。一个二维数组&am…

超维空间S2无人机使用说明书——32、使用yolov7进行目标识别

引言&#xff1a;为了提高yolo识别的质量&#xff0c;提高了yolo的版本&#xff0c;改用yolov7进行物体识别&#xff0c;同时系统兼容了低版本的yolo&#xff0c;包括基于C的yolov3和yolov4&#xff0c;也有更高版本的yolov8。 简介&#xff0c;为了提高识别速度&#xff0c;系…

Android Studio各种Gradle常见报错问题及解决方案

大家好&#xff0c;我是咕噜铁蛋&#xff01;在开发Android应用程序时&#xff0c;我们可能会遇到各种Gradle错误。这些错误可能来自不同的原因&#xff0c;例如依赖项问题、配置错误、版本冲突等。今天我通过搜索整理了一下&#xff0c;在这篇文章中&#xff0c;我将分享一些常…

AI 绘画StableDiffusionWebui图生图

介绍 stable-diffusion-webui AI绘画工具&#xff0c;本文介绍图生图&#xff0c;以一张图片做底图优化生成。 例如&#xff1a;上传一张真人照片&#xff0c;让AI把他改绘成动漫人物&#xff1b;上传画作线稿&#xff0c;让AI自动上色&#xff1b;上传一张黑白照&#xff0c…

001 图书增删改查 SSM MySQL

技术框架&#xff1a;Spring SpringMVC Mybatis JSP MySQL 001 图书增删改查 SSM MySQL package com.demo.controller;import com.demo.pojo.Book; import com.demo.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.spri…

Uniapp + Vue3 + Pinia + Vant3 框架搭建

现在越来越多项目都偏向于Vue3开发&#xff0c;想着uniapp搭配Vue3试试效果怎么样&#xff0c;接下来就是详细操作步骤。 初始化Uniapp Vue3项目 App.vue setup语法 <script setup>import {onLaunch,onShow,onHide} from dcloudio/uni-apponLaunch(() > {console.l…

人工智能_机器学习072_SVM支持向量机_人脸识别模型训练_训练时间过长解决办法_数据降维_LFW人脸数据建模与C参数选择---人工智能工作笔记0112

我们先来看一下之前的代码: import numpy as np 导入数学计算库 from sklearn. svm import SVC 导入支持向量机 线性分类器 import matplotlib.pyplot as plt 加载人脸图片以后,我们用pyplot把人脸图片数据展示一下 from sklearn.model_selection import train_test_split 人脸…

Mysql-干净卸载教程

卸载 服务停掉 先把mysql服务停掉&#xff0c;如下点击右键&#xff0c;停止运行。 删除C盘内文件 接下来c盘里面的三个文件下的MySQL一一删除&#xff0c;需要注意的是 需要注意的是programdata文件下可能 隐藏了MySQL文件&#xff0c;所以可以在查看选项显示隐藏的文件。 …

032 - STM32学习笔记 - TIM基本定时器(一) - 定时器基本知识

032 - STM32学习笔记 - TIM定时器&#xff08;一&#xff09; - 基本定时器知识 这节开始学习一下TIM定时器功能&#xff0c;从字面意思上理解&#xff0c;定时器的基本功能就是用来定时&#xff0c;与定时器相结合&#xff0c;可以实现一些周期性的数据发送、采集等功能&#…

python实现批量替换目录下多个后缀为docx文档内容

批量替换目录下多个后缀为docx文档内容 摘要&#xff1a; 本文将介绍如何使用Python实现批量替换目录下多个后缀为docx文档内容。通过使用Python的os和glob模块&#xff0c;我们可以轻松地遍历目录下的所有文件&#xff0c;并对每个文件进行操作。此外&#xff0c;我们还将使用…

使用Ubuntu22+Minikube快速搭建K8S开发环境

安装Vmware 这一步&#xff0c;可以参考我的如下课程。 安装Ubuntu22 下载ISO镜像 这里我推荐从清华镜像源下载&#xff0c;速度会快非常多。 下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/22.04.3/ 如果你报名了我的这门视频课程&#xf…

【网络编程】网络通信基础——简述TCP/IP协议

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、ip地…

26、湾湾国立阳明交通大学、湾湾长庚纪念医院提出:ALL Attention U-Net,独属头部CT分割的[玛格丽特]

本文由台湾国立阳明交通大学、台湾长庚纪念医院于2023年12月16日在arXiv<Image and Video Processing>发表。 论文地址&#xff1a; 2312.10483.pdf (arxiv.org) 0、Abstract 脑出血在 Head CT扫描中作为第一线工具&#xff0c;帮助专家诊断不同类型的出血。然而&…