zoukankan      html  css  js  c++  java
  • 0148-leetcode算法实现之排序链表-sortLinkedList-python&golang实现

    给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

    进阶:

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

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

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/sort-list

    思路:
    -1.断链
    -2.合并
    -3.循环

    python

    # 0148.排序链表
    """
    知识点1:归并排序的整体思想
    知识点2:找到一个链表的中间节点的方法
    知识点3:合并两个已排好序的链表为一个新的有序链表
    """
    # 参考:https://leetcode-cn.com/problems/sort-list/solution/pai-xu-lian-biao-di-gui-die-dai-xiang-jie-by-cherr/
    
    class ListNode:
        def __init__(self, val):
            self.val = val
            self.next = None
    
    class Solution:
        def sortList1(self, head: ListNode) -> ListNode:
            """
            迭代,时间O(nlogn), 空间O(1)
            :param head:
            :return:
            """
            length = self.getLength(head)
            dummy = ListNode(-1)
            dummy.next = head
    
            step = 1
            while step < length:
                # 每次变换步长, pre和cur指针初始化在表头
                pre, cur = dummy, dummy.next
                while cur:
                    h1 = cur # 第一部分头,第二次循环之后,cur为剩余部分头,不断往后把链表按照步长step分成一块一块...
                    h2 = self.split(h1, step) # 第二部分头
                    cur = self.split(h2, step) # 剩余部分头
                    temp = self.merge(h1, h2) # 一二部分合并
                    pre.next = temp # 前面部分与排序好的连接
                    while pre.next:
                        pre = pre.next # pre移动到排序好部分的末尾
                step = step * 2
    
            return dummy.next
    
        def sortList(self, head: ListNode) -> ListNode:
            """
            递归法,时间O(nlogn), 空间O(logn)
            :param head:
            :return:
            """
            if head is None or head.next is None:
                return head
            slow, fast = head, head.next
    
            # 断链
            while fast != None and fast.next != None:
                slow = slow.next
                fast = fast.next.next
            rightHead = slow.next
            slow.next = None
            # 递归
            left = self.sortList(head)
            right = self.sortList(rightHead)
            # 合并
            return self.merge(left, right)
    
        def merge(self, h1, h2: ListNode) -> ListNode:
            dummy = ListNode(-1)
            p = dummy
    
            while h1 != None and h2 != None:
                if h1.val < h2.val:
                    p.next = h1
                    h1 = h1.next
                else:
                    p.next = h2
                    h2 = h2.next
                p = p.next
            p.next = h1 or h2
    
            return dummy.next
    
        def getLength(self, head: ListNode) -> int:
            cnt = 0
            while head:
                cnt += 1
                head = head.next
            return cnt
    
        def split(self, head: ListNode, step: int) -> ListNode :
            # 断链操作
            if head == None:
                return head
            cur = head
            for i in range(1, step):
                if cur.next != None:
                    cur = cur.next
            right = cur.next
            cur.next = None # 以cur为界断开原链
            # 返回右链链头
            return right
    
    

    golang

    // 迭代
    func sortList1(head *ListNode) *ListNode {
    	length := getLength(head)
    	dummy := &ListNode{}
    	dummy.Next = head
    
    	for step := 1; step < length; step = step * 2 {
    		pre, cur := dummy, dummy.Next
    		for cur != nil {
    			h1 := cur
    			h2 := split(h1, step)
    			cur = split(h2, step)
    			temp := merge(h1, h2)
    			pre.Next = temp
    			for pre.Next != nil {
    				pre = pre.Next
    			}
    		}
    	}
    	return dummy.Next
    }
    
    func getLength(head *ListNode) int {
    	cnt := 0
    	cur := head
    	for cur != nil {
    		cnt++
    		cur = cur.Next
    	}
    	return cnt
    }
    
    func split(head *ListNode, step int) *ListNode {
    	if head == nil {
    		return head
    	}
    	cur := head
    	for i := 1; i < step; i++ {
    		if cur.Next != nil {
    			cur = cur.Next
    		}
    	}
    	right := cur.Next
    	cur.Next = nil
    	return right
    }
    
    // 递归 leetcode提示初始时间限制
    func sortList(head *ListNode) *ListNode {
    	if head == nil || head.Next == nil {
    		return head
    	}
    	// 断链
    	slow, fast := head, head.Next
    	for fast != nil && fast.Next != nil {
    		slow = slow.Next
    		fast = fast.Next
    	}
    	rightHead := slow.Next
    	slow.Next = nil
    	// 递归
    	left := sortList(head)
    	right := sortList(rightHead)
    
    	return merge(left, right)
    }
    
    func merge(h1, h2 *ListNode) *ListNode {
    	dummy := &ListNode{}
    	p := dummy
    	for h1 != nil && h2 != nil {
    		if h1.Val < h2.Val {
    			p.Next = h1
    			h1 = h1.Next
    		} else {
    			p.Next = h2
    			h2 = h2.Next
    		}
    		p = p.Next
    	}
    	if h1 != nil {
    		p.Next = h1
    	} else {
    		p.Next = h2
    	}
    	return dummy.Next
    }
    
    
  • 相关阅读:
    Office 转 PDF & PDF 转 SWF Windows版
    Office 转 PDF & PDF 转 SWF Linux版
    MP4Box 编译 和相应命令
    CentOS VNC 安装与配置,方便进行运程桌面连接
    系统时钟&&硬件时钟
    IPtables中SNAT、DNAT和MASQUERADE的含义
    配置SNAT实现共享上网
    DNAT & SNAT
    linux应急操作
    linux-清理linux空间
  • 原文地址:https://www.cnblogs.com/davis12/p/15506571.html
Copyright © 2011-2022 走看看