一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情
题目(Insertion Sort List)
链接:https://leetcode-cn.com/problems/insertion-sort-list
解决数:916
通过率:68.7%
标签:链表 排序
相关公司:bytedance facebook amazon
给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。
插入排序 算法的步骤:
- 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
- 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
- 重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。
对链表进行插入排序。
示例 1:
输入: head = [4,2,1,3]
输出: [1,2,3,4]
示例 2:
输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]
提示:
- 列表中的节点数在
[1, 5000]范围内 -5000 <= Node.val <= 5000
思路
见注释
代码
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var insertionSortList = function(head) {
// current 当前需要找到位置插入的节点
// currentPre 当前插入节点之前的节点
let current = head.next, currentPre = head;
if(!current) return head;
// 正向判断
while(current) {
// compareHead 用来从头部往current节点之间遍历的节点指针
// shouldUpdateCurrentPre 用来判断该current是否需要移动位置
// 需要移动位置则currentPre无需更新, 不移动位置则需要将currentPre更新
let compareHead = head, shouldUpdateCurrentPre = true;
// currentNext 暂存下个节点, headPre暂存 compareHead移位之前的节点,找到插入位置需要更新compareHead 与 current的位置
let currentNext = current.next, headPre = null;
// head 往后寻找值比 current大的节点
while(compareHead !== current) {
if(compareHead.val > current.val) {
// 如果current插入位置不是头节点之前
if(headPre) {
// 更新compareHead 与 current位置
headPre.next = current;
current.next = compareHead;
}else {
// 插入位置是头结点之前 更新current与头结点位置
let tempNode = head;
head = current;
current.next = tempNode;
}
// 移出current之后 前后节点连接
currentPre.next = currentNext;
// 不需要更新currentPre
shouldUpdateCurrentPre = false;
break;
}
// 赋值headPre
headPre = compareHead;
// compareHead后移
compareHead = compareHead.next;
}
// 更新currentPre
shouldUpdateCurrentPre && (currentPre = current);
// 更新current
current = currentNext;
}
return head;
};