Leetcode LinkedList题型总结(1)

LinkedList 的操作.

  • 加入
  • 删除
  • 翻转

这是三个最常考的类型.

先来讲翻转

还是经典题, Revert Linked List
然后通过这一题可以延伸出很多种不同的翻转.
在Linked List 中最常要考虑的就是保留开始的头节点, 因为每一次你链表变动的时候很容易就会把头节点丢了,而且别忘了测边界值当节点是 None 或者下一个是 None 的时候怎么办.
画个图吧

class Solution:
    # @param {ListNode} head
    # @return {ListNode}
    def reverseList(self, head):
        # prev 为一个空指针,
        prev = None
        # 当链表还有节点的时候
        while head:
            # 先用 temp 储存, 因为后面指针移动会用到
            temp = head
            # 拿到下一个节点, 将会变成前一个的头, 链表的移动体现在了这一步
            head = head.next
            # temp, 同时也是当前的节点, 下一个会变成前一个节点或者为空
            temp.next = prev
            # 指针指向当前节点
            prev = temp
        return prev

# 还有递归的做法, 但是一般不会考

class Recursive:
    def reverseList(self, head):
        return self._reverse(head)

    def _reverse(self, head, prev=None):
        if not head:    return prev
        tail = head.next
        head.next = prev
        return self._reverse(tail, head)

从这一题,延伸出了别的题目, 在面试中有些考官很喜欢问 follow up, 也一般是第一道题
转换类型的题目有以下:

Reverse Linked List II

reverse linked list 的变形, 其实只是部分的换,而且要照顾头尾的节点

class Solution:
    # @param head, a ListNode
    # @param m, an integer
    # @param n, an integer
    # @return a ListNode
    def reverseBetween(self, head, m, n):
        if not head or not head.next:   return head
        # 要一个临时的头节点, 为了在完成之后还能够找回原来的头节点
        head2 = ListNode(-1)
        head2.next = head

        # 第一个指针指向第m节点的前一个位置
        previous = head2
        for i in range(m, 1, -1):
            previous = previous.next
        # 创造第二个指针, 跟head2用法一样
        tail = previous.next
        # 这一步是为了断开链表, 防止转换过程出现问题
        previous.next = None
        # 从这一步开始跟之前是一模一样的
        current = tail
        for i in range(n - m + 1, 0, -1):
            if i == 1:
                tail.next = current.next
            temp = current.next
            current.next = previous.next
            previous.next = current
            current = temp
        return head2.next

Swap Nodes in Pairs
这一题也是 reverse linked list 的变形, 就是每翻转两个节点的时候,要注意连上前后的节点, 而且要留意长度为单数的时候要处理None

class Solution:
    # @param a ListNode
    # @return a ListNode
    def swapPairs(self, head):

        if not head or not head.next:   return head
        head2, node = ListNode(-1), head
        pointer = head2
        # 每两个节点的转换
        while node and node.next:
            # 这里从 next 变成了 next next, 因为我们要连上第三个节点
            temp = node.next.next
            pointer.next = node.next        # frist node
            pointer = pointer.next          # second node
            # swap
            pointer.next = node             # link to head
            # 指针先保留,指向第三个
            pointer = pointer.next          # third node
            # 连上第三个
            node = temp
        # 处理单个情况
        if node:
            pointer.next = node
            pointer = pointer.next
        pointer.next = None
        return head2.next

Reorder List
这一道题要处理的问题是要把头尾连起来, reserve 的原理还是一样,重点是怎么拿到后半段的节点,然后按照前后前后的顺序连起来.
有两种方法,第一是先探测到中间点在哪里, 然后两个指针从头尾依次相连, 不需要额外空间. 另外一种方法是把双数的放到一个 stack 里面去,然后 pop 出来的节点就是已经倒过来的顺序了, 但是需要 O(n) 的空间.

class Solution:
    class TwoPointers:
        # @param head, a ListNode
        # @return nothing
        def reorderList(self, head):
            if not head or not head.next or not head.next.next:
                return
            slow, fast = head, head.next
            while fast and fast.next:
                fast = fast.next.next
                slow = slow.next
            if fast:
                slow = slow.next

            # 分成两半
            head2 = slow.next
            slow.next = None

            head2 = self.reverse(head2)
            h1 = head;  h2 = head2
            while h2:
                temp1 = h1.next
                temp2 = h2.next
                h1.next = h2
                h2.next = temp1
                h1 = temp1
                h2 = temp2

        def reverse(self, head):
            pointer = head; head2 = None
            while pointer:
                temp = pointer.next
                pointer.next = head2
                head2 = pointer
                pointer = temp
            return head2

    class Stack:
        def reorderList(self, head):
            if not head or not head.next or not head.next.next:
                return
            stack = []
            slow, fast = head, head

            while fast and fast.next:
                fast = fast.next.next
                slow = slow.next

            if fast:
                slow = slow.next

            stack = []
            # 把后半段加进 stack
            while slow:
                stack.append(slow)
                slow = slow.next

            slow = head

            while stack:
                temp = slow.next
                node = stack.pop()
                slow.next = node
                # 重新连上单数的下一个节点
                node.next = temp
                slow = temp

            slow.next = None

Partition List
这题比较简单, 只是用两个指针来把链表分成两个部分, 然后再把两个头连起来而已.

class Solution:
    # @param head, a ListNode
    # @param x, an integer
    # @return a ListNode
    def partition(self, head, x):
        if not head:   return head
        sHead, bHead = ListNode(0), ListNode(0)
        sTail, bTail = sHead, bHead
        while head:
            if head.val < x:
                sTail.next = head
                sTail = sTail.next
            else:
                bTail.next = head;
                bTail = bTail.next
            head = head.next
        bTail.next = None
        sTail.next = bHead.next
        return sHead.next

Rotate List
这一题只是把链表拆分后重新连起来, 没有调换顺序, 主要考察的地方是怎样找到应该断开的 K 点

class Solution:
    # @param head, a ListNode
    # @param k, an integer
    # @return a ListNode
    def rotateRight(self, head, k):
        if not head or k == 0:  return head
        pointer, index = head, 1
        # 先知道链表总长
        while pointer.next:
            pointer = pointer.next
            index += 1
        # 计算出应该断开的 diff 点
        diff = index - k % index    # mod is for n larger than length
        pointer.next = head         # connect head and tail
        while diff > 0:
            pointer = pointer.next
            diff -= 1
        head = pointer.next         # split the linked list
        pointer.next = None         # tail
        return head
    原文作者:taobit
    原文地址: https://www.jianshu.com/p/a08708c08274
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞