【每日一题】148. 排序链表 归并算法

153 阅读2分钟

归并算法

这是leetcode中 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 = []

输出:[]

 

提示:

链表中节点的数目在范围 [0, 5 * 104] 内

-105 <= Node.val <= 105

 

进阶:你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

通过次数234,947提交次数352,622

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/so…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

算法实现


/**
 * 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 sortList = function(head) {
//之前是对数组进行排序,这次是对链表进行排序
//使用冒泡排序,不过交换交换的时候需要注意,也不用怎么注意,直接交换值就可以,又不用交换节点 22点56分
//这个没有长度怎么使用冒泡
//遍历一遍,然后取出所有的值,然后再放进去?
    // var res = []
    // var cur = head
    // //找出所有的值
    // while(cur){
    //     res.push(cur.val)
    //     cur = cur.next
    // }
    // //从小到大进行排序
    // res.sort((a,b)=>a-b)
    // cur = head
    // var i = 0
    // //输入排序后的值
    // while(cur){
    //     cur.val = res[i++]
    //     cur = cur.next
    // }
    // return head


    //如果是上面的做法,行得通,但是不是符合刷题的目的
    //看了题解后,是使用递归的算法,就是将链表两半,然后对链表进行排序组合,重复递归后,再进行排序
    
    //合并两个有序链表
    var merge = (list1,list2) => {
        //从新列一个链表而不是在原来的基础上追加‘
        var curNode = new ListNode(0);
        var head = curNode
        var cur1 = list1;
        var cur2 = list2;
        while(cur1 !== null && cur2 !==null){
            //如果第一个比较小的,就把,给cur1链表,相同长度,或者长度相差一
            if(cur1.val <= cur2.val){
                head.next = cur1
                cur1 = cur1.next
            }else{
                head.next = cur2
                cur2 = cur2.next
            }
            //下一个头部
            head = head.next
        }
        if(cur1 !== null){
            head.next = cur1
        }
        if(cur2 !== null){
            head.next = cur2
        }
        return curNode.next
    }
    //将链表进行划分,分为fast指针和show指针,fast先走两步,而show指针只是走一步,如果fast先到的话,说明show到了中点,然后return 这个中间点
    var tosort = (list,tail) =>{
        //需要加上判断,才能够进行返回
        if(list == null) return list
        if(list.next == tail){
            //重复了,如果两个数的话,就不用进行划分了
            list.next = null
            return list
        }
        var cur = list;
        var fast = cur;
        var show = cur;
        var mid ;
        //如果fast跟尾部相同的时候,
        while(fast !== tail){
            show = show.next
            fast = fast.next
            if(fast !== tail){
                fast = fast.next
            }
        }
        mid = show
        return merge(tosort(cur,mid), tosort(mid,tail))
    }
    return tosort(head,null)
};

复杂度分析

时间复杂度:O(nlogn)

空间复杂度:O(logn)

最后


这是我2022年分享的「leetcode」第NO.7篇文章。