「前端刷题」147.对链表进行插入排序(MEDIUM)

127 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

题目(Insertion Sort List)

链接:https://leetcode-cn.com/problems/insertion-sort-list
解决数:916
通过率:68.7%
标签:链表 排序 
相关公司:bytedance facebook amazon 

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

插入排序 算法的步骤:

  1. 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
  2. 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
  3. 重复直到所有输入数据插入完为止。

下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。

对链表进行插入排序。

 

示例 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;
};