leetcode刷题_(sort,LinkedList)_code148(链表排序)

坚强是说给别人听的谎言 提交于 2020-02-13 22:00:56

code148: Sort List

Add to List

Share
Sort a linked list in O(n log n) time using constant space complexity.

Example 1:

Input: 4->2->1->3
Output: 1->2->3->4
Example 2:

Input: -1->5->3->4->0
Output: -1->0->3->4->5

解答:
看到logn基本确定是有二分的想法在里面

我的想法:
类似快排,每个链的head作为pivot,然后遍历,小的新建链放在左边,大的新建链放在右边。得到三个(left, pivot, right),然后进行整合为新链。内部进行递归细分整合。

代码:

class Solution:###TLE  ###quick sort
    def sortList(self, head: ListNode) -> ListNode:
        return self.sort_node(head)

    def sort_node(self, node):
        #print('#')
        if not node:
            return None
        else:
            #print(node.val)
            new_node1, new_node2 = ListNode(0), ListNode(0)
            new_nodel, new_noder = ListNode(0), ListNode(0)
            new_nodel.next = new_node1
            new_noder.next = new_node2
            # new_node1.next = node
            pivot = node
            # new_node1 = new_node1.next
            while node.next:
                #print('???')
                if node.next.val < pivot.val:
                    new_node1.next = node.next
                    new_node1 = new_node1.next
                else:
                    new_node2.next = node.next
                    new_node2 = new_node2.next
                node = node.next
            #if new_node1.next:
            new_node1.next = None
            new_node2.next = None

            new_nodel.next.next = self.sort_node(new_nodel.next.next)
            new_noder.next.next = self.sort_node(new_noder.next.next)
            return self.merge(new_nodel.next.next, pivot, new_noder.next.next)

    def merge(self, node1, pivot, node2):
        #print('?')
        new_node = ListNode(0)
        if node1:
            new_node.next = node1
            #print(node1.val)
            while node1:
                #print('??????')
                if node1.next:
                    print(node1.val)
                    node1 = node1.next
                else:
                    break
            #print(node1.val)
            node1.next = pivot

        else:
            new_node.next = pivot

        pivot.next = node2
        return new_node.next

这段代码最后的例子超时。分析是因为在合并的时候做的左半边再次遍历导致时间复杂度提升。

先看看后面解答里面别人提供的归并思想。其实最开始也是想到的归并,但是归并需要找到中点,不太好操作就否决了。现在的操作:
1 设置 fast slow, 前者进行.next.next遍历,后者进行.next遍历。终止位置的slow就是中点。
2 然后分离左右部分,将左边最后设置为None,右边头设置为slow
3 进行递归
4 合并,类似归并的做法。
代码:

class Solution:#merge sort
    def sortList(self, head: ListNode) -> ListNode:
        #print(head.val)
        if not head or not head.next:
            return head
        else:
            slow = head
            fast = head.next
            while slow and  fast:
                if fast.next:
                    if fast.next.next:
                        fast = fast.next.next
                    else:
                        break
                else:
                    break
                slow = slow.next
            #print(slow.val)
            r = slow.next
            slow.next = None
            l = head
            l = self.sortList(l)
            r = self.sortList(r)
            return self.merge(l,r)

    def merge(self, h1,h2):
        pre = tail = ListNode(0)
        while h1 or h2:
            if not h2:
                pre.next = h1
                break
            elif not h1:
                pre.next = h2
                break
            elif h1.val>h2.val:
                pre.next = h2
                pre = pre.next
                h2 = h2.next
            else:
                pre.next = h1
                pre = pre.next
                h1 = h1.next
        return tail.next

tips:
1 寻找链表中点的有效方法之一就是进行fast,slow的操作
2 链表中间切断时,结尾需要连上None

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!