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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容

  • Single Linked List 相比较另一个基本的数据结构array,linked list有几个优势:尺寸...
    dol_re_mi阅读 8,183评论 0 3
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,745评论 0 33
  • //leetcode中还有花样链表题,这里几个例子,冰山一角 求单链表中结点的个数----时间复杂度O(n)这是最...
    暗黑破坏球嘿哈阅读 1,518评论 0 6
  • LeetCode 刷题随手记 - 第一部分 前 256 题(非会员),仅算法题,的吐槽 https://leetc...
    蕾娜漢默阅读 17,779评论 2 36
  • 2. Add Two Numbers 先初始化两个结点,一个用来做head,一个作为指引node不断向下延续的指针...
    Morphiaaa阅读 920评论 0 0