147. [链表]对链表进行插入排序
Posted suphxlin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了147. [链表]对链表进行插入排序相关的知识,希望对你有一定的参考价值。
147. 对链表进行插入排序
方法一:插入排序
准备curr,prev
当前节点和前驱节点用于判断是否有逆序的情况;再准备一个哨兵节点用于排序链表的插入。
tmp.next != curr && tmp.next.val < curr.val
对应的逻辑关系是:此时对应当前节点curr
的值(<)前驱节点(prev)的值这一情况(前后节点逆序);tmp.next != curr && tmp.next.val < curr.val
的作用是在从头寻找curr
节点要插入的位置。
// 执行耗时:9 ms,击败了39.44% 的Java用户
// 内存消耗:38.1 MB,击败了92.29% 的Java用户
class Solution {
public ListNode insertionSortList(ListNode head) {
if (head == null || head.next == null){
return head;
}
ListNode prev = head, curr = head.next; // 使用一个前驱节点prev便于后续节点的删除操作
ListNode sentinel = new ListNode(0); // 使用一个哨兵节点,便于链表的插入操作
sentinel.next = head;
while (curr != null){
if (prev.val < curr.val){ // 前后节点已经有序,无需重排
prev = curr;
curr = curr.next;
} else {
ListNode tmp = sentinel;
while (tmp.next != curr && tmp.next.val < curr.val){ // 从头寻找cur节点要插入的位置
tmp = tmp.next;
}
prev.next = curr.next; // 删除当前节点
curr.next = tmp.next; // 将当前节点连接到对于位置
tmp.next = curr;
curr = prev.next;
}
}
return sentinel.next;
}
}
方法二:插入排序(提速版)
利用前一个插入的位置进行提速,即每次先把当前要插入的元素和前一个插入点比较,如果比它大,那么就从这里开始搜索,否则才需要从链表头开始搜索。
// 执行耗时:2 ms,击败了99.26% 的Java用户
// 内存消耗:38.4 MB,击败了66.36% 的Java用户
class Solution {
public ListNode insertionSortList(ListNode head) {
ListNode sentinel = new ListNode(0);
ListNode prev = sentinel;
for (ListNode node = head; node != null;)
{
ListNode curr = node;
node = node.next;
// 与前一个插入点比较决定从哪里开始搜索
if (curr.val < prev.val) prev = sentinel;
while (prev.next != null && curr.val > prev.next.val) prev = prev.next;
curr.next = prev.next;
prev.next = curr;
}
return sentinel.next;
}
}
以上是关于147. [链表]对链表进行插入排序的主要内容,如果未能解决你的问题,请参考以下文章