链表14:单链表的排序
前面我们连续多节分析了链表反转的问题,你有没有注意到最大的问题都是指针要进行调整时的指向问题?具体又体现在两个方面,一个是反转相关的问题,一个是合并相关的问题,有些算法还是两个的结合。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:单链表的排序相关推荐
- 【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)
一.线性表 1.1 概念与特点 1.2 线性表的存储结构 1.3 常见操作 1.4 应用场景 二.链表 2.1 链表简介 2.2 单向链表(单链表) 2.21 基本概念 2.22 单链表基本操作 2. ...
- 线性表详解(静态链表、单链表、双向链表、循环链表)
目录 申明 1. 线性表的定义 2. 线性表的抽象数据类型 3. 线性表的顺序存储结构 3. 1 顺序存储定义 3. 2 顺序存储方式 3. 3 数据长度与线性表长度区别 3. 4 地址计算方法 4. ...
- python之链表、单链表、双向链表、单向循环链表
python之链表.单链表.双向链表.单向循环链表 链表 顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时,又需要进行数据的搬迁,所以使用起来并非很灵活 链表结构可以充分利用计算机 ...
- 数据结构5: 链表(单链表)的基本操作及C语言实现
逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表那样也相互紧挨着.恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为线性表的链式存储. 由于分散存储,为了能够体现出数据元素之间的逻辑关 ...
- 单链表删除所有值为x的元素_C/C++编程笔记:如何使用C++实现单链表?单链表的基本定义...
如何弥补顺序表的不足之处? 第一次学习线性表一定会马上接触到一种叫做顺序表(顺序存储结构),经过上一篇的分析顺序表的优缺点是很显然的,它虽然能够很快的访问读取元素,但是在解决如插入和删除等操作的时候, ...
- php链表和联表的区别,PHP_浅谈PHP链表数据结构(单链表),链表:是一个有序的列表,但 - phpStudy...
浅谈PHP链表数据结构(单链表) 链表:是一个有序的列表,但是它在内存中是分散存储的,使用链表可以解决类似约瑟夫问题,排序问题,搜索问题,广义表 单向链表,双向链表,环形链表 PHP的底层是C,当一个 ...
- python单链表实现具体例子_Python实现数据结构线性链表(单链表)算法示例
本文实例讲述了Python实现数据结构线性链表(单链表)算法.分享给大家供大家参考,具体如下: 初学python,拿数据结构中的线性链表存储结构练练手,理论比较简单,直接上代码. #!/usr/bin ...
- php mysql 链表_浅谈PHP链表数据结构(单链表)
链表:是一个有序的列表,但是它在内存中是分散存储的,使用链表可以解决类似约瑟夫问题,排序问题,搜索问题,广义表 单向链表,双向链表,环形链表 PHP的底层是C,当一个程序运行时,内存分成五个区(堆区, ...
- c语言数组指定位置插入和删除_玩转C语言链表,单链表/双向链表的建立/遍历/插入/删除...
最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...
- 线性表:3.链表,单链表详解与C语言实现
逻辑结构上一个挨一个的数据,在实际存储时,并没有像顺序表那样也相互紧挨着.恰恰相反,数据随机分布在内存中的各个位置,这种存储结构称为 线性表的链式存储 . 由于分散存储,为了能够体现出数据元素之间的逻 ...
最新文章
- linux的三个时间
- Java---设计模块(单例的变形)(多例)
- 如何快速实现 Wordpress 博客域名更换?
- LeetCode刷题——整数反转
- opencv3.1.0+VS2013 环境配置
- java面向对象编程基础实验报告_20155313 实验三《Java面向对象程序设计》实验报告...
- yum下载rpm包、源码包安装
- mysql心得笔记_mysql总结笔记
- Inception-v4论文总结
- 计算机处理答题卡原理,基于图像处理的答题卡自动阅卷系统的设计与实现
- 【uni-app的ui组件】uni-ui如何安装使用教程
- Java实现简易版金山打字
- 冯诺依曼结构和哈佛结构
- 游戏思考11:游戏服务器类型简单分类(有服务器的会讲的详细一点)
- Python中seek()函数的使用方法--一文读懂
- 【Java】文件管理器
- 释放智能边缘广阔机遇,英特尔携手生态伙伴构建万物互联未来
- [4G5G专题-114]:部署 - LTE PRACH前导码格式、ZC序列的生成规则与规划
- 如何用计算机做出折线图,Numbers怎么做折线图 Numbers制作折线图教程
- 54. 流编辑器sed技术概览