Leetcode 算法面试冲刺 实战 二(链表)(九)

99 · 重排链表

给定一个单链表L: L0→L1→…→Ln-1→Ln,
重新排列后为:L0→Ln→L1→Ln-1→L2→Ln-2→…
必须在不改变节点值的情况下进行原地操作。

在这里插入图片描述
在这里插入图片描述
我的思路是从中间往后的链表反转,然后再合并。但是不知道为什么,时间复杂度那里过不去。

from lintcode import (
    ListNode,
)

"""
Definition of ListNode
class ListNode(object):
    def __init__(self, val, next=None):
        self.val = val
        self.next = next
"""

class Solution:
    """
    @param head: The head of linked list.
    @return: nothing
    """
    def reorderList(self, head: ListNode):
        # write your code here
        if head == None or head.next == None:
            return head
        
        dummy = ListNode(-1, head)
        cur = dummy.next

        # 找中点
        middle = self.find_middle_node(cur)
        # 反转中点到最后的链表
        reverse_head = self.reverse_list(middle)
        middle.next = None

        # 合并
        res = self.merge_list(head, reverse_head)
        return res
    
    def merge_list(self, head1, head2):
        res = head1
        while head1 and head2:
            temp1 = head1.next
            head1.next = head2
            temp2 = head2.next
            head2.next = temp1
            head1 = temp1
            head2 = temp2
        return res
        
    def reverse_list(self, cur_node):
        while cur_node.next:
            temp = cur_node.next
            temp.next = cur_node
            cur_node = temp
        return cur_node

        
    def find_middle_node(self, cur):
        slow, fast = cur, cur
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
        return slow


在这里插入图片描述

是reverse那里没写对,进入死循环了,下面是修改后的代码:

from lintcode import (
    ListNode,
)

"""
Definition of ListNode
class ListNode(object):
    def __init__(self, val, next=None):
        self.val = val
        self.next = next
"""

class Solution:
    """
    @param head: The head of linked list.
    @return: nothing
    """
    def reorderList(self, head: ListNode):
        # write your code here
        if head == None or head.next == None:
            return head
        
        dummy = ListNode(-1, head)
        cur = dummy.next

        # 找中点
        middle = self.find_middle_node(cur)
        # 反转中点到最后的链表
        reverse_head = self.reverse_list(middle)
        middle.next = None

        # 合并
        res = self.merge_list(head, reverse_head)
        return res
    
    def merge_list(self, head1, head2):
        res = head1
        while head1 and head2:
            temp1 = head1.next
            head1.next = head2
            temp2 = head2.next
            head2.next = temp1
            head1 = temp1
            head2 = temp2
        return res
        

    def reverse_list(self, cur_node):
        pre = None
        while cur_node:
            temp = cur_node.next
            cur_node.next = pre
            pre = cur_node
            cur_node = temp
        return pre

        
    def find_middle_node(self, cur):
        slow, fast = cur, cur
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
        return slow

在这里插入图片描述
注意边界,注意特殊情况,这道题是中等题,中等题一般是2个简单题的组合,这道题就是反转和合并的组合。

599 · 向循环有序链表插入节点

给一个来自已经排过序的循环链表的节点,写一个函数来将一个值插入到循环链表中,并且保持还是有序循环链表。给出的节点可以是链表中的任意一个单节点。返回插入后的新链表。
在这里插入图片描述
一开始写的代码:但是我发现x不论比链表的值都大,或者都小,都是插入到max后,min前,所以后面2个while可以复用。

"""
Definition of ListNode
class ListNode(object):
    def __init__(self, val, next=None):
        self.val = val
        self.next = next
"""

class Solution:
    """
    @param node: a list node in the list
    @param x: An integer
    @return: the inserted new list node
    """
    def insert(self, node, x):
        # write your code here
        # 边界
        cur_node = ListNode(x)
        if node == None: return cur_node

        # 遍历 寻找插入点 终止条件是回到起点
        start = node
        node = node.next
        while node != start:
            # 进行比较
            if node.val <= x and node.next.val >= x:
                return self.ins_node(cur_node, node)
            node = node.next
        
        if node.val == x: return self.ins_node(cur_node, node) 

        # x比链表值都大/小
        while (node.val < x) and (node.val < node.next.val):
            node = node.next
        return self.ins_node(cur_node, node)


        # x比链表值都小
        while (node.val > x) and (node.val < node.next.val):
            node = node.next
        return self.ins_node(cur_node, node)



    def ins_node(self, cur_node, node):
        cur_node.next = node.next
        node.next = cur_node
        return cur_node


优化后的代码:

"""
Definition of ListNode
class ListNode(object):
    def __init__(self, val, next=None):
        self.val = val
        self.next = next
"""

class Solution:
    """
    @param node: a list node in the list
    @param x: An integer
    @return: the inserted new list node
    """
    def insert(self, node, x):
        # write your code here
        # 边界
        cur_node = ListNode(x)
        if node == None: return cur_node

        # 遍历 寻找插入点 终止条件是回到起点
        start = node
        node = node.next
        while node != start:
            # 进行比较
            if node.val <= x and node.next.val >= x:
                return self.ins_node(cur_node, node)
            node = node.next
        
        # x比链表值都大/小/等
        while node.val < node.next.val:
            node = node.next
        return self.ins_node(cur_node, node)


    def ins_node(self, cur_node, node):
        cur_node.next = node.next
        node.next = cur_node
        return cur_node

下面是官方题解:
由于已经是排序好的链表。
所以只需顺序扫描一遍链表即可。
需要注意的是,若为最大或是最小,需要额外判断。

class Solution:
    # @param {ListNode} node a list node in the list
    # @param {int} x an integer
    # @return {ListNode} the inserted new list node
    def insert(self, node, x):
        # Write your code here
        if node is None:
            node = ListNode(x)
            node.next = node
            return node

        p = node
        prev = None
        while True:
            prev = p
            p = p.next
            if x <= p.val and x >= prev.val:
                break

            if (prev.val > p.val) and (x < p.val or x > prev.val):
                break

            if p is node:
                break

        newNode = ListNode(x)
        newNode.next = p
        prev.next = newNode
        return newNode

在这里插入图片描述
这里我没看懂。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值