Leetcode题linked list medium 2/19/24/61/82/86/92/109/138/142/143/147/148,Python多种解法(十三)

前文

  继上篇链表简单篇结束,我们继续分享完剩余的中等难度篇。话不多说,让我们开始吧!

2. Add Two Numbers
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        题意是求两个链表的各个数相加的和,如果高于10,则往下一个数+1
        解法围绕divmod这个求解+余数来完成,如果有carry值,则表明高于10,此时carry为1
        所以每个节点就是v1+v2+carry的和
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        root = n = ListNode(0)
        carry = 0
        while l1 or l2 or carry:
            v1 = v2 = 0
            if l1:
                v1 = l1.val
                l1 = l1.next
            if l2:
                v2 = l2.val
                l2 = l2.next
            carry, val = divmod(v1 + v2 + carry, 10)
            n.next = ListNode(val)
            n = n.next
        return root.next

19. Remove Nth Node From End of List

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    定义快慢指针,让快指针先跑n个格,这样当快指针跑完的时候,慢指针刚好停在从end开始的n个格,然后直接跳过即可
    Runtime: 16 ms, faster than 95.44% of Python online submissions for Remove Nth Node From End of List.
    Memory Usage: 11.8 MB, less than 26.64% of Python online submissions for Remove Nth Node From End of List.
    """
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        fast = slow = head
        for _ in range(n):
            fast = fast.next
        if not fast:
            return head.next
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return head


class Solution2(object):
    """
    用递归来完成,这个思路也是很强。当递归到链表结尾时,此时的i即表示最后1个数的开始索引即1,当i>n,即表示位于要删除的前一位,
    然后跳过即表示删除。最后再判断当n过大的情况,直接反馈head.next
    Runtime: 24 ms, faster than 62.50% of Python online submissions for Remove Nth Node From End of List.
    Memory Usage: 11.9 MB, less than 7.94% of Python online submissions for Remove Nth Node From End of List.
    """
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        def index(node):
            if not node:
                return 0
            i = index(node.next) + 1
            if i > n:
                node.next.val = node.val
            return i
        index(head)
        return head.next
24. Swap Nodes in Pairs


# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    pre is the previous node. Since the head doesn't have a previous node, I just use self instead. Again,
    a is the current node and b is the next node.To go from pre -> a -> b -> b.next to pre -> b -> a -> b.next
    Runtime: 16 ms, faster than 93.29% of Python online submissions for Swap Nodes in Pairs.
    Memory Usage: 11.8 MB, less than 50.85% of Python online submissions for Swap Nodes in Pairs.
    """
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        pre,pre.next = self,head
        while pre.next and pre.next.next:
            a = pre.next
            b = a.next
            pre.next, b.next, a.next = b,a,b.next
            pre = a
        return self.next
61. Rotate List

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    """
    题目需要根据给定的数字依次反转链表,根据如下代码还是蛮清晰的,先求出总长度n,然后求出需要从
    哪个位置开始反转,要注意的是k%n来求余避免k>n的情况!接着通过tail=tail.next找到开始反转的上一个位置。
    比较难理解的是最后一步:先指定开始反转的tail.next,然后把该链表的tail.next重置为None,这样返回的结果就截止在反转,
    最后再把pre这原本指向链表最后位置的重置到开头,形成一个循环!
    Runtime: 20 ms, faster than 95.00% of Python online submissions for Rotate List.
    Memory Usage: 11.6 MB, less than 94.65% of Python online submissions for Rotate List.
    """
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        n ,pre ,current = 0 ,None ,head
        while current:
            pre ,current = current ,current.next
            n += 1

        while not n or not k % n:
            return head

        tail = head
        for i in range( n - k % n -1):
            tail = tail.next

        next, tail.next, pre.next = tail.next, None, head
        return next
82. Remove Duplicates from Sorted List II
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    题意是要删除重复项,指定两个节点指向head,然后判断当前head和head.next值是否相等,相等则继续;
    整体的思路是比较清晰的,就是指针的指向相对比较复杂
    Runtime: 32 ms, faster than 64.44% of Python online submissions for Remove Duplicates from Sorted List II.
    Memory Usage: 11.7 MB, less than 70.21% of Python online submissions for Remove Duplicates from Sorted List II.
    """
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        tmp = dummy = ListNode(0)
        tmp.next = head
        while head and head.next:
            if head.val == head.next.val:
                while head and head.next and head.val == head.next.val:
                    head = head.next
                head = head.next
                dummy.next = head
            else:
                dummy = dummy.next
                head = head.next

        return tmp.next
86. Partition List
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    这个解法太简洁易懂了!一开始我的想法就是只定义一条链表,但我发现没办法插入小于x的值到链表最前方,
    看到这个解法直接定义两条链表,小的归小的,大的归大的,最后合并即可,简直太强!
    Runtime: 20 ms, faster than 90.18% of Python online submissions for Partition List.
    Memory Usage: 11.8 MB, less than 68.50% of Python online submissions for Partition List.
    """
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        l1 = h1 = ListNode(0)
        l2 = h2 = ListNode(0)
        while head:
            if head.val < x:
                l1.next = head
                l1 = l1.next
            else:
                l2.next = head
                l2 = l2.next
            head = head.next
        l2.next = None
        l1.next = h2.next
        return h1.next
92. Reverse Linked List II
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    题目要求按照索引m和n将这之间的链表反转,所以思路很清晰,先定位到m的位置,然后对到n之间的链表用单链表反转
    也就是leetcode第206的方法来做,反转后指定链表的指向即可
    Runtime: 16 ms, faster than 92.06% of Python online submissions for Reverse Linked List II.
    Memory Usage: 12.1 MB, less than 11.07% of Python online submissions for Reverse Linked List II.
    """
    def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        if m == n:
            return head

        dummyNode = ListNode(0)
        dummyNode.next = head
        pre = dummyNode

        for i in range(m - 1):
            pre = pre.next

        # reverse the [m, n] nodes
        reverse = None
        cur = pre.next
        for i in range(n - m + 1):
            next = cur.next
            cur.next = reverse
            reverse = cur
            cur = next

        pre.next.next = cur
        pre.next = reverse

        return dummyNode.next


109. Convert Sorted List to Binary Search Tree
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    """
    题意是将有序链表转为二叉树,因为没有要求二叉树是有序的,所以相对简单很多。
    先依次将链表的值插入列表,最后利用递归直接根据长度的一半生成二叉树即可,效率也是非常快
    Runtime: 100 ms, faster than 99.58% of Python online submissions for Convert Sorted List to Binary Search Tree.
    Memory Usage: 23.9 MB, less than 38.87% of Python online submissions for Convert Sorted List to Binary Search Tree.
    """
    def sortedListToBST(self, head):
        """
        :type head: ListNode
        :rtype: TreeNode
        """
        ls = []
        while head:
            ls.append(head.val)
            head = head.next
        return self.helper(ls, 0, len(ls) - 1)

    def helper(self, ls, start, end):
        if start > end:
            return None
        if start == end:
            return TreeNode(ls[start])
        mid = (start + end) >> 1
        root = TreeNode(ls[mid])
        root.left = self.helper(ls, start, mid - 1)
        root.right = self.helper(ls, mid + 1, end)
        return root

class Solution2(object):
    """
    解法二则是定义快慢指针,快指针定位结尾,慢指针定位中间,然后根据中间和头部分别生成树的右边和左边,可以说和第一种差别不大
    Runtime: 120 ms, faster than 64.52% of Python online submissions for Convert Sorted List to Binary Search Tree.
    Memory Usage: 18.1 MB, less than 99.23% of Python online submissions for Convert Sorted List to Binary Search Tree.
    """
    def sortedListToBST(self, head):
        """
        :type head: ListNode
        :rtype: TreeNode
        """
        if not head:
            return
        if not head.next:
            return TreeNode(head.val)
        dummy = ListNode(0)
        dummy.next = head
        slow, fast = dummy, head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        root = TreeNode(slow.next.val)
        root.right = self.sortedListToBST(slow.next.next)
        slow.next = None
        root.left = self.sortedListToBST(head)
        return root
138. Copy List with Random Pointer


# Definition for a Node.
class Node(object):
    def __init__(self, val, next, random):
        self.val = val
        self.next = next
        self.random = random

class Solution(object):
    """
    先构造字典,将老链表和新链表一一对应,这样就构造了一个纯next的链表,然后再循环即可
    Runtime: 392 ms, faster than 33.67% of Python online submissions for Copy List with Random Pointer.
    Memory Usage: 14.6 MB, less than 100.00% of Python online submissions for Copy List with Random Pointer.
    """
    def copyRandomList(self, head):
        """
        :type head: Node
        :rtype: Node
        """
        nodeDict = dict()
        new_head = dummy = Node(0, None, None)
        pointer = head
        while pointer:
            val_node = Node(pointer.val, pointer.next, None)
            nodeDict[pointer] = val_node
            new_head.next = val_node
            new_head, pointer = new_head.next, pointer.next
        while head:
            if head.random:
                nodeDict[head].random = nodeDict[head.random]
            head = head.next
        return dummy.next
142. Linked List Cycle II
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head: return None
        visited = set()
        while head:
            if head in visited:
                return head
            visited.add(head)
            head = head.next
        return None

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        slow, fast = head, head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                break
        if not fast or not fast.next:
            return None
        slow = head
        while slow != fast:
            slow = slow.next
            fast = fast.next
        return fast
143. Reorder List

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    """
    For linked list 1->2->3->4-5, the code first makes the list to be 1->2->3->4<-5 and 4->None, then make 3->None,
    for even number linked list: 1->2->3->4, make first 1->2->3<-4 and 3->None, and lastly do not forget to make 2->None.
    Runtime: 84 ms, faster than 84.57% of Python online submissions for Reorder List.
    Memory Usage: 29.5 MB, less than 93.87% of Python online submissions for Reorder List.
    """
    def reorderList(self, head):
        """
        :type head: ListNode
        :rtype: None Do not return anything, modify head in-place instead.
        """
        if not head:
            return
        # ensure the first part has the same or one more node
        fast, slow = head.next, head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
        # reverse the second half
        p = slow.next
        slow.next = None
        node = None
        while p:
            nxt = p.next
            p.next = node
            node = p
            p = nxt
        # combine head part and node part
        p = head
        while node:
            tmp = node.next
            node.next = p.next
            p.next = node
            p = p.next.next #p = node.next
            node = tmp
147. Insertion Sort List
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    题意是插入排序 注释也是写的非常清楚了
    Runtime: 156 ms, faster than 81.60% of Python online submissions for Insertion Sort List.
    Memory Usage: 15.1 MB, less than 78.57% of Python online submissions for Insertion Sort List.
    """
    def insertionSortList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur = dummy = ListNode(0)
        while head:
            if cur and cur.val > head.val: # reset pointer only when new number is smaller than pointer value
                cur = dummy
            while cur.next and cur.next.val < head.val: # classic insertion sort to find position
                cur = cur.next
            cur.next, cur.next.next, head = head, cur.next, head.next # insert
        return dummy.next
148. Sort List
# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    """
    题意是对链表排序,用归并排序来做链表,也是相当易懂的
    Runtime: 236 ms, faster than 52.04% of Python online submissions for Sort List.
    Memory Usage: 26.3 MB, less than 65.08% of Python online submissions for Sort List.
    """
    def merge(self, h1, h2):
        dummy = tail = ListNode(None)
        while h1 and h2:
            if h1.val < h2.val:
                tail.next, tail, h1 = h1, h1, h1.next
            else:
                tail.next, tail, h2 = h2, h2, h2.next

        tail.next = h1 or h2
        return dummy.next

    def sortList(self, head):
        if not head or not head.next:
            return head

        pre, slow, fast = None, head, head
        while fast and fast.next:
            pre, slow, fast = slow, slow.next, fast.next.next
        pre.next = None

        return self.merge(*map(self.sortList, (head, slow)))

总结

  本次分享到此,拜拜~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值