// 排序链表
//给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表
package Top31_40;
import Util.ListNode;
import java.util.ArrayList;
import java.util.List;
// 排序链表
//给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
public class Top31 {
// 方法一 转换数组排序之后再创建链表 时间复杂度和空间复杂度都是O(n)
public static ListNode sortList(ListNode head) {
if (head == null) {
return null;
}
List<ListNode> nodes = new ArrayList<>();
ListNode cur = head;
while (cur != null) {
nodes.add(cur);
cur = cur.next;
}
nodes.sort((s1, s2) -> (s1.val - s2.val));
ListNode head2 = nodes.get(0);
cur = head2;
for (int i = 1; i <= nodes.size(); i++) {
if (i == nodes.size()) {
cur.next = null;
return head2;
}
cur.next = nodes.get(i);
cur = cur.next;
}
return head2;
}
//方法二 快排
public ListNode fastSortList(ListNode head) {
//边界
if (head == null || head.next == null) return head;
//伪头结点
ListNode pre = new ListNode(0, head);
//快排
quickSort(pre, null);
//返回头结点
return pre.next;
}
//输入时伪头结点和尾节点null
void quickSort(ListNode pre, ListNode end) {
//如果节点数小于1就返回
if (pre == end || pre.next == end || pre.next.next == end) return;
//选第一个节点为基准
ListNode b = pre.next;
//建立临时链表
ListNode cur = new ListNode(0);
//临时左右两指针
ListNode r = b, l = cur;
//遍历,右指针下一节点为end,说明当前是最后一个元素,结束
while (r.next != end) {
//如果当前元素小于基准,就加入临时链表,并在原链表中删除
if (r.next.val < b.val) {
l.next = r.next;
l = l.next;
r.next = r.next.next;
} else {
//不小于基准,右指针后移
r = r.next;
}
}
//临时链表接在原链表前面,并把伪头结点指向临时节点头结点
l.next = pre.next;
pre.next = cur.next;
//对基准的左右两边递归,注意输入都是伪头结点和两链表的尾节点的下一节点
quickSort(pre, b);
quickSort(b, end);
}
public static void main(String[] args) {
int[] nums = {4, 2, 1, 3};
ListNode node = ListNode.setNodes(0, nums);
ListNode.printListData(sortList(node));
}
}
harryptter / LeetcodeTop100 · GitCode