【算法训练】LeetCode#148 排序链表
一、描述
148. 排序链表
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
示例 1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:
输入:head = []
输出:[]
二、思路
- 排序方法有很多,先用冒泡思想,每次找到最大值放到末尾。
- 时间复杂度为n方,超时了。
- 归并排序,递归调用,不断拆分最后两两排序合并。
三、解题
public static class Solution {
public static class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
// 冒泡 ,超时了
public ListNode sortList(ListNode head) {
if (head == null || head .next == null){
return head;
}
ListNode curNode = head;
int length = 0; // 得到长度
while (curNode != null){
length++;
curNode = curNode.next;
}
boolean flag = false; // 默认false,如果变换过则true,如果结束一轮还是false,表明已经完全升序了
for (int i = 0 ; i<length; i++){
ListNode preNode = null;
curNode = head;
flag = false;
for (int j = 0 ; j < length-i-1 ; j++){
if (curNode.val > curNode.next.val){
// 交换位置
ListNode tmp = curNode.next.next; // 防止后续链表丢失
curNode.next.next = curNode;
if (preNode == null){
// 如果是头节点位置变换,则需要移动head,否则将丢失头节点
head = curNode.next;
preNode = curNode.next; // 前驱节点向后移动一位
} else {
// 如果非头节点变换
// 前一节点指向当前节点的后一节点
preNode.next = curNode.next;
}
preNode = curNode.next;
curNode.next = tmp;
flag = true;
} else {
preNode = curNode; // 前驱节点向后移动一位
curNode = curNode.next;
}
if (!flag){
return head;
}
}
}
return head;
}
// 归并排序
public ListNode sortListV2(ListNode head) {
return proccess(head,null);
}
// 递归主体,一半一半的拆分
public ListNode proccess(ListNode head,ListNode tail){
if (head == null){
return null;
}
if (head.next == tail){
// 单节点时,直接返回该节点
head.next = null; // 断链
return head;
}
ListNode slow = head, fast = head;
while (fast != tail) {
slow = slow.next;
fast = fast.next;
if (fast != tail) {
fast = fast.next;
}
}
// 找到上半链表的尾巴 slow
ListNode mid = slow;
ListNode list1 = proccess(head, mid); // 递归拆分
ListNode list2 = proccess(mid, tail);
ListNode sorted = mergeList(list1, list2); // 排序好的合并
return sorted;
}
// 合并两个有序链表
public ListNode mergeList(ListNode head1,ListNode head2){
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
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 if (temp2 != null){
temp.next = temp2;
}
return dummyHead.next;
}