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
这里我没看懂。