Leetcode 21. 合并两个有序链表
难度 ⭐
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
思路
当两个链表都非空时,选链表头最小的那个添加到辅助链表中;当有一个链表为空,另一个链表非空的时候,直接一股脑塞进辅助链表。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(-1) #辅助链表头
tmp = head #向辅助链表中插入新节点
left_pointer = l1
right_pointer = l2
while(left_pointer and right_pointer): #neither of the two lists is empty
if left_pointer.val < right_pointer.val:
tmp.next = ListNode(left_pointer.val)
tmp = tmp.next
left_pointer = left_pointer.next
else:
tmp.next = ListNode(right_pointer.val)
tmp = tmp.next
right_pointer = right_pointer.next
if left_pointer:
while(left_pointer):
tmp.next = ListNode(left_pointer.val)
tmp = tmp.next
left_pointer = left_pointer.next
if right_pointer:
while(right_pointer):
tmp.next = ListNode(right_pointer.val)
tmp = tmp.next
right_pointer = right_pointer.next
return head.next
✅ 总结
当需要建立一个新链表时,可以先建一个不含有任何数据的链表头head,然后再用tmp指向head,每次都向tmp.next插入数据即可
Leetcode 148. 排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
思路
很自然的想到归并排序。那么我们可以用上一题的方法合并有序列表了!唯一的问题是,列表是不支持随机访问的,那么应该如何通过一次遍历找到列表的中点呢?
这里我们使用“快指针慢指针”方法。快指针从head->next出发,一次移动两格;慢指针从head出发,一次移动一格。
class Solution(object):
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head or not head.next: #终止条件
return head
slow = head #慢指针
fast = head.next #快指针
while(fast and fast.next):
slow = slow.next
fast = fast.next.next
l2_head = slow.next ##第二个列表
slow.next = None ##截断!
return self.mergeTwoLists(self.sortList(head),self.sortList(l2_head))
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(-1)
tmp = head
left_pointer = l1
right_pointer = l2
while(left_pointer and right_pointer): #neither of the two lists is empty
if left_pointer.val < right_pointer.val:
tmp.next = ListNode(left_pointer.val)
tmp = tmp.next
left_pointer = left_pointer.next
else:
tmp.next = ListNode(right_pointer.val)
tmp = tmp.next
right_pointer = right_pointer.next
if left_pointer:
while(left_pointer):
tmp.next = ListNode(left_pointer.val)
tmp = tmp.next
left_pointer = left_pointer.next
if right_pointer:
while(right_pointer):
tmp.next = ListNode(right_pointer.val)
tmp = tmp.next
right_pointer = right_pointer.next
return head.next
❗ 总结
快指针慢指针这个方法没有想到。
Leetcode 236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
思路
很自然的想到,可以将两个节点都层层向上找parent,一直找到根节点。例如节点4对应的列表为[4,2,5,3]; 节点6对应的列表为[6,5,3]. 然后从右到左找到最后一个重合的数即可。这里,最后一个重合的数为5.
但是看到节点的定义,竟然没有parent这个值!那么怎么办呢?不要慌,用一个dict(哈希表)记录一下每个节点的parent就好了。
# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution(object):
parent_hash = {}
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
p = p.val
q = q.val
stack_p = [p]
stack_q = [q]
self.in_traverse(root) ##得到parent哈希表
while(p != root.val):
stack_p.append(self.parent_hash[p])
p = self.parent_hash[p]
while(q != root.val):
stack_q.append(self.parent_hash[q])
q = self.parent_hash[q]
print(self.parent_hash,stack_q,stack_p)
ans = -1
while(len(stack_q)*len(stack_p)!=0 and stack_q[-1] == stack_p[-1]):
ans = stack_p[-1]
stack_p = stack_p[:-1]
stack_q = stack_q[:-1]
return TreeNode(ans)
def in_traverse(self,root):
if root == None:
return
self.in_traverse(root.left)
if root.left:
self.parent_hash[root.left.val] = root.val
if root.right:
self.parent_hash[root.right.val] = root.val
self.in_traverse(root.right)
❕ 总结
没有想到要用哈希表记录parent