前面我们连续多节分析了链表反转的问题,你有没有注意到最大的问题都是指针要进行调整时的指向问题?具体又体现在两个方面,一个是反转相关的问题,一个是合并相关的问题,有些算法还是两个的结合。LeetCode148题又是一个典型的题目。

LeetCode148题 :给定一个无序单链表,实现单链表的排序(按升序排序)。

示例1:

输入:head = [4,2,1,3]输出:[1,2,3,4]

思路:涉及到节点移动的场景,肯定少不了调整指针,这里还必须小心两端的处理。脑子不够还是画图来凑,画个图、走几步再写会比较好一些。这个题目同样有多种处理方式,一种是直接根据类似冒泡排序的方式硬写,但是很难写对,而且个大量改变指针会导致执行超时,是出力不讨好的事情。所以我们需要更加优化的方式。

1 偷梁换柱,通过数组排序再赋值回去

过程是这样的:首先循环一次获得链表的长度,然后创建一个数组。

再循环一次,将链表节点的值都赋值给数组对数组进行排序。

最后将数组的值再写回到链表里。

这样做是将链表问题变成了数组问题,也不矢为一种方法,代码就很好些了:

public ListNode sortInList(ListNode head) {        if(head == null) {            return head;        }           ListNode p = head;        ListNode q = head;        ListNode t = head;        int n = 0;        while (p != null) {            p = p.next;            n++;        }        int[] arr = new int[n];        for (int i = 0; i < arr.length; i++) {            arr[i] = head.val;            head = head.next;        } //这里给我们省去了无数麻烦。如果有精力,可以现场自己实现一个        Arrays.sort(arr);        int i = 0;        while (q != null) {            q.val = arr[i++];            q = q.next;        }        return t;    }

2 归并排序法

上面的方法虽然能解决问题,但是面试官可能不满意,因为他就想考察你链表的控制能力。这里我们可以使用归并排序的方法来进行,先利用快慢指针找出链表的中点,然后分为两个链表,一直分,知道无法分为止,然后自底而上排序归并。

代码就是这样:

 public ListNode sortInList (ListNode head) {       if(head == null || head.next == null)            return head;        //使用快慢指针找到中点        ListNode slow = head, fast = head.next;        while(fast!=null && fast.next !=null){            slow = slow.next;            fast = fast.next.next;        }        //分割为两个链表        ListNode newList = slow.next;        slow.next = null;        //将两个链表继续分割,这里必须用递归,否则一堆拆散的链表难以管理        ListNode left = sortInList(head);        ListNode right = sortInList(newList);         ListNode lhead = new ListNode(-1);        ListNode res = lhead;        //归并排序,如果想不明白,可以看完后面的经典排序专题再来看        while(left != null && right != null){            if(left.val < right.val){                lhead.next = left;                left = left.next;            }else{                lhead.next = right;                right = right.next;            }            lhead = lhead.next;        }        //判断左右链表是否为空        lhead.next = left!=null?left:right;        return res.next;     }

这个题目有自顶向下和自下而上两种方式,我们先熟练掌握一种吧。

3.利用冒泡方式进行排序

关键时刻如果想不到好的方式,根据题目硬写也可以的。这时候如果卷面整洁,思路清晰,能得个及格分,但是可能运行超时。

import java.util.*;/* * public class ListNode { *   int val; *   ListNode next = null; * } */​public class Solution {    /**     *      * @param head ListNode类 the head node     * @return ListNode类     */    public ListNode sortInList (ListNode head) {      if(head==null)           return null;       ListNode oldP=head,oldHead ;       ListNode newHead=head;      while(oldP!=null){          oldHead=oldP;          oldP=oldP.next;      newHead=   insertSeq(newHead,oldHead);        }       return newHead;    }    public ListNode insertSeq(ListNode newHead,ListNode oldHead){        //空        if(newHead==null){            return oldHead;        }        //最前面        if(newHead.val>=oldHead.val){            oldHead.next=newHead;            newHead=oldHead;            return newHead;        }        ListNode newCur=newHead;        //中间位置        while(newCur.val<oldHead.val && newCur.next!=null){           newCur=newCur.next;        }        oldHead.next=newCur.next;        newCur.next=oldHead;         return newHead;            }}

链表14:单链表的排序相关推荐

  1. 【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)

    一.线性表 1.1 概念与特点 1.2 线性表的存储结构 1.3 常见操作 1.4 应用场景 二.链表 2.1 链表简介 2.2 单向链表(单链表) 2.21 基本概念 2.22 单链表基本操作 2. ...

  2. 线性表详解(静态链表、单链表、双向链表、循环链表)

    目录 申明 1. 线性表的定义 2. 线性表的抽象数据类型 3. 线性表的顺序存储结构 3. 1 顺序存储定义 3. 2 顺序存储方式 3. 3 数据长度与线性表长度区别 3. 4 地址计算方法 4. ...

  3. python之链表、单链表、双向链表、单向循环链表

    python之链表.单链表.双向链表.单向循环链表 链表 顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时,又需要进行数据的搬迁,所以使用起来并非很灵活 链表结构可以充分利用计算机 ...

  4. 数据结构5: 链表(单链表)的基本操作及C语言实现

    逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表那样也相互紧挨着.恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为线性表的链式存储. 由于分散存储,为了能够体现出数据元素之间的逻辑关 ...

  5. 单链表删除所有值为x的元素_C/C++编程笔记:如何使用C++实现单链表?单链表的基本定义...

    如何弥补顺序表的不足之处? 第一次学习线性表一定会马上接触到一种叫做顺序表(顺序存储结构),经过上一篇的分析顺序表的优缺点是很显然的,它虽然能够很快的访问读取元素,但是在解决如插入和删除等操作的时候, ...

  6. php链表和联表的区别,PHP_浅谈PHP链表数据结构(单链表),链表:是一个有序的列表,但 - phpStudy...

    浅谈PHP链表数据结构(单链表) 链表:是一个有序的列表,但是它在内存中是分散存储的,使用链表可以解决类似约瑟夫问题,排序问题,搜索问题,广义表 单向链表,双向链表,环形链表 PHP的底层是C,当一个 ...

  7. python单链表实现具体例子_Python实现数据结构线性链表(单链表)算法示例

    本文实例讲述了Python实现数据结构线性链表(单链表)算法.分享给大家供大家参考,具体如下: 初学python,拿数据结构中的线性链表存储结构练练手,理论比较简单,直接上代码. #!/usr/bin ...

  8. php mysql 链表_浅谈PHP链表数据结构(单链表)

    链表:是一个有序的列表,但是它在内存中是分散存储的,使用链表可以解决类似约瑟夫问题,排序问题,搜索问题,广义表 单向链表,双向链表,环形链表 PHP的底层是C,当一个程序运行时,内存分成五个区(堆区, ...

  9. c语言数组指定位置插入和删除_玩转C语言链表,单链表/双向链表的建立/遍历/插入/删除...

    最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...

  10. 线性表:3.链表,单链表详解与C语言实现

    逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表那样也相互紧挨着.恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为 线性表的链式存储 . 由于分散存储,为了能够体现出数据元素之间的逻 ...

最新文章

  1. linux的三个时间
  2. Java---设计模块(单例的变形)(多例)
  3. 如何快速实现 Wordpress 博客域名更换?
  4. LeetCode刷题——整数反转
  5. opencv3.1.0+VS2013 环境配置
  6. java面向对象编程基础实验报告_20155313 实验三《Java面向对象程序设计》实验报告...
  7. yum下载rpm包、源码包安装
  8. mysql心得笔记_mysql总结笔记
  9. Inception-v4论文总结
  10. 计算机处理答题卡原理,基于图像处理的答题卡自动阅卷系统的设计与实现
  11. 【uni-app的ui组件】uni-ui如何安装使用教程
  12. Java实现简易版金山打字
  13. 冯诺依曼结构和哈佛结构
  14. 游戏思考11:游戏服务器类型简单分类(有服务器的会讲的详细一点)
  15. Python中seek()函数的使用方法--一文读懂
  16. 【Java】文件管理器
  17. 释放智能边缘广阔机遇,英特尔携手生态伙伴构建万物互联未来
  18. [4G5G专题-114]:部署 - LTE PRACH前导码格式、ZC序列的生成规则与规划
  19. 如何用计算机做出折线图,Numbers怎么做折线图 Numbers制作折线图教程
  20. 54. 流编辑器sed技术概览

热门文章

  1. 新手上路:ADAMS 基础知识讲解(图文并茂)【转载仿真论坛】(二)
  2. Claude回答ARINC653标准在中国大陆的应用情况
  3. fl studio中文版水果2020下载Keymaker-CORE.rar及使用常见问题教程
  4. 【汇智学堂】-python小游戏(太空阻击之四-飞碟入侵)
  5. 单点登录3 手撕代码模拟CAS实现单点登录
  6. 【手把手教你树莓派3 (三)】scp命令传文件
  7. Golang中Int32转换为int16丢失精度的具体过程
  8. Java语言程序设计——学习笔记(辽宁大学,王青松主讲)
  9. 广告精准推送项目介绍
  10. UE4实时抠图,直播,绿幕