教练明天我想做这里面的题!
快慢指针研究透了不香嘛!
LC148 排序链表
我的刷题笔记
排序链表
老题新做
之前快速排序也是拿这个题开的头
结果时间复杂度直接给我爆炸了(为啥要快排链表啊!!)
1.读题
2.解题思路
归并排序…嘶 忘掉了鸭
只能先看着题解慢慢回忆下了
本题暂时使用个递归的做法
参考题解 【148.排序链表】归并排序 详解 java
链表中的归并排序我们需要注意——
- 需要找到链表的中间结点 这里定义为
midNode
- 需要进行两个链表的合并
康康动图就明白了~
3.代码逻辑
【1】想到要将链表通过递归 一步一步分开
康康动图就明白了~
【2】这样就需要找到中间结点
【3】写出 找到中间结点 的函数
【4】之后不断地进行递归排序
这里其实没太弄懂 是咋每一趟排序都做到从小到大排序的23333
【5】最后要把两个链表合并起来
别忘了写合并函数~
4.Java代码
class Solution {
public ListNode sortList(ListNode head) {
if (head == null || head.next == null){
return head;//退出条件
}
ListNode midNode = findMidNode(head);//这个是链表的中间结点
//之后我们要写出 找到中间结点的函数~
ListNode rightHead = midNode.next;//定义好右边链表的头结点
midNode.next = null;//在中间结点处断开链表~
ListNode left = sortList(head);//开始递归~对左边的链表进行排序
ListNode right = sortList(rightHead);//对右边的链表进行排序
return merge(left, right);//将左右链表进行合并
}
//01 写出寻找中间结点的函数
//其实这个本身也可以作为一道题嘛~
public ListNode findMidNode(ListNode head){
if (head == null || head.next == null){
return head;//退出条件
}
//熟悉的双指针法~快指针一下跑俩结点 慢指针跑一个
//等快指针指向空或快指针的下一位指向空 就说明慢指针是指向中间辽~
ListNode slow = head;
ListNode fast = head.next.next;
while(fast != null && fast.next != null){
//注意这里的条件
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//02 写出链表合并的函数
public ListNode merge(ListNode left, ListNode right){
ListNode dummyNode = new ListNode(0);
ListNode current = dummyNode;
while(left != null && right != null){
if (left.val < right.val) {
current.next = left;
left = left.next;
}
else{
current.next = right;
right = right.next;
}
current = current.next;
}
current.next = left != null ? left : right;
return dummyNode.next;
}
}