Leetcode【86、92、148、206】

问题描述:【Linked List】86. Partition List
解题思路:

这道题是给一个链表和整数 x,将小于 x 的数按位置顺序放在链表左侧,大于等于 x 的按位置顺序放在右侧。

类似于快排的划分过程有木有。可以建立两个指针 l_end 和 r_end,分别指向 x 的左右两部分的尾部。再建立一个指针指向当前结点 cur,便于链表的遍历。因为我们不知道第一个结点和 x 的关系,所以可以建一个空结点 node 指向 head,最后 head.next 就是答案。

  • l_end 初始化为 head(空结点),r_end 初始化为 None,cur 指向 head.next 第一个结点;
  • 遍历 cur:
    1、如果 cur.val < x and r_end == None,说明刚开始碰到的都是小于 x 的,就只需要移动 l_end 到 cur 的位置即可;
    2、 如果 cur.val < x,这个时候 r_end 不为空,利用这三个指针进行交换和移动即可;
    3、否则,碰到的都是大于等于 x 的,就只需要移动 r_end 到 cur 的位置即可。

时间复杂度为 O(n),空间复杂度为 O(1)。

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

class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        node = ListNode(-1)  # 头结点
        node.next = head
        head = node
        l_end, r_end, cur = head, None, head.next
        while cur:
            if cur.val < x and r_end == None:  # 没遇到比 x 大的,只移动 l_end
                l_end = cur
            elif cur.val < x:  # r_end 不为 None,利用三指针交换
                r_end.next = cur.next  # 交换
                cur.next = l_end.next
                l_end.next = cur
                l_end = cur  # 移动
                cur = r_end
            else:
                r_end = cur
            cur = cur.next
        return head.next

问题描述:【Linked List】92. Reverse Linked List II
解题思路:

这道题是给一个链表和区间 [m, n],反转区间内的数字。

这道题和下面的 Leetcode 206 思路相同。对于一个区间的反转,需要用 notr 记录不用反转区间的最后一个位置;用 start 记录反转区间的头指针;为了反转方便,再定义 pre 和 cur 分别为前一个指针和当前指针。遍历 cur,找到反转区间,进行指针的交换和移动操作即可。

时间复杂度为 O(n),空间复杂度为 O(1)。

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

class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        if not head:
            return head
        # notr: 不用反转区间的最后一个位置
        # start: 反转区间的头指针
        # pre, cur:前一个指针和当前指针
        notr, start, pre, cur = None, None, None, head
        i = 1
        while cur:
            if i <= m:
                if i == m:  # 初始化四个指针
                    notr = pre
                    start = cur
                pre = cur
                cur = cur.next
            elif m < i <= n:  # 在起始位置的下一个位置反转,通过指针交换完成
                pre.next = cur.next # 交换
                cur.next = start
                start = cur
                if m == 1:  # 从头开始
                    head = cur
                else:  # 从中间开始
                    notr.next = start
                cur = pre.next  # 移动
            else:
                break
            i += 1
        return head

问题描述:【Linked List】148. Sort List
解题思路:

这道题是给一个链表,对链表排序。要求时间复杂度 O(nlogn),空间复杂度 O(1)。

首先,肯定能想到要么是使用快速排序,要么是归并排序。刚好上面的 Leetcode 86 为链表划分,所以就借助其思想实现了快排。但是最后一个 case 超时了(嘤嘤嘤),代码如下:

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

class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        if not head or not head.next:  # 递归出口
            return head
        pivot = head.val
        le, ri, cur = head, None, head.next  # 左右区间划分
        while cur:
            if cur.val < pivot and ri == None:
                le = cur
            elif cur.val < pivot:
                ri.next = cur.next  # 交换
                cur.next = le.next
                le.next = cur
                le = cur  # 移动
                cur = ri
            else:
                ri = cur
            cur = cur.next
        ri = le.next  # 左右两侧排序
        le.next = None
        lp = self.sortList(head.next)
        rp = self.sortList(ri)
        if lp == None:   # 将基准 head.val 放到中间
            head.next = rp
            lp = head
        else:
            cur = lp
            while cur.next:
                cur = cur.next
            cur.next = head
            head.next = rp
        return lp  # 返回链表头结点

看了题解,有人使用归并排序 mergeSort 通过了,同样可以做到时间复杂度为 O(nlogn),空间复杂度为 O(1)。代码如下(不是我写的,懒得再写一次了):

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

class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        if head is None:
            return None
        p, i = head, 0
        while p:
            i += 1
            p = p.next
        return self.mergeSort(head, i)[0]
            
    def mergeSort(self,head,k):
        if k == 1:
            next = head.next
            head.next = None
            return head, next
        left_head, next = self.mergeSort(head, k//2)
        right_head, next = self.mergeSort(next, k-(k//2))
        return self.merge(left_head, right_head), next

    def merge(self, h1, h2):
        dummy = ListNode(0)
        p = dummy
        while h1 and h2:
            if h1.val <= h2.val:
                p.next = h1
                p = p.next
                h1 = h1.next
            else:
                p.next = h2
                p = p.next
                h2 = h2.next
        if h1 is None and h2 is not None:
            p.next = h2
        elif h2 is None and h1 is not None:
            p.next = h1
        return dummy.next

问题描述:【Linked List】206. Reverse Linked List
解题思路:

这道题是给一个链表,将链表反转。

链表反转只需要两个相邻指针 pre 和 cur 即可。对于 cur 遍历,先交换(3 次操作)后移动指针到正确的位置,时间复杂度为 O(n)。

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

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