109. 有序链表转换二叉搜索树
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定的有序链表: [-10, -3, 0, 5, 9],
一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
def findmid(l,r):
fast=l
last=l
while fast!=r and fast.next!=r: #链表找中点用快慢指针,这里注意快指针的本身和下一个位置是不是与最后一样判断
last=last.next
fast=fast.next.next
return last
def m(l,r):
if l==r:return #这边注意判断条件就和之前数组里面要是l>r就ruturn
node=findmid(l,r)
root=ListNode(node.val)
root.left=m(l,node)
root.right=m(node.next,r)
return root
return m(head,None) # 要return
或者转换成数组来做
if not head: return None
lis=[]
while head:
lis.append(head.val)
head=head.next
N=len(lis) #此时链表变成lis数组
left,right =0,N-1
def m(l,r):
if l>r:
return None
mid = (l+r+1)//2
root = ListNode(lis[mid])
root.left =m(l,mid-1)
root.right =m(mid+1,r)
return root
return m(left,right)
98. 验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:
2
/ \
1 3
输出: true
res=[]
def m(root): # 中序遍历 左根右
if not root:
return
m(root.left)
res.append(root.val)
m(root.right)
m(root)
r=res[:]
return sorted(r)==res and len(res)==len(set(res)) #按顺序 且没有重复的
法2:
mi=float('-inf')
ma=float('inf')
def m(root,mi,ma):
if not root:
return True
if root.val<=mi: #注意这边含有等号,等号时也是False
return False
if root.val>=ma:
return False
return m(root.left,mi,root.val) and m(root.right,root.val,ma)
return m(root,mi,ma)
二叉树的前中后序遍历
前:根左右
if not root:return []
res=[]
stack=[root]
while stack:
r=stack.pop()
res.append(r.val)
if r.right:
stack.append(r.right)
if r.left: #左节点后加进去 为了先pop出来
stack.append(r.left)
return res
后:左右根 可以非递归时用根右左 最后结果倒过来 和前序遍历类似
stack=[root]
res=[]
if not root:
return res
while stack:
r=stack.pop()
res.append(r.val)
if r.left:
stack.append(r.left)
if r.right:
stack.append(r.right)
return res[::-1]
中:左根右 这里因为根在中间 所以和前序和后序处理不同
res=[]
stack=[]
while stack or root:
while root:
stack.append(root)
root=root.left
r=stack.pop()
res.append(r.val)
root=r.right
return res
递归 : 后序
if not root:
return []
res=[]
def m(root):
if not root:
return
#前序 res.append(root.val)
m(root.left)
#中序 res.append(root.val)
m(root.right)
res.append(root.val) #后序 res.append(root.val)
m(root)
return res
236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
def m(root):
if not root or root==p or root==q: # 递归
return root
l,r=m(root.left),m(root.right)
if not l:return r
if not r:return l
if l and r:return root #同时不为空 则pq在左右子树一边一个直接返回root
return m(root)
寻找路径的代码
def back(node, path, target, res):
if not node:
return
if node == target:
path.append(node)
res.extend(path[:]) # 注意用[:],即浅拷贝
return
path.append(node)
back(node.left, path, target, res) # 回溯
back(node.right, path, target, res)
path.pop() # 记得恢复状态
res_p = [] # 两个变量,分别存储从根到目标点的路径
res_q = []
back(root, [], p, res_p)
back(root, [], q, res_q)
# 让 res_p 存储路径较小的那个,方便下面遍历查找操作
103. 二叉树的锯齿形层次遍历
给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
例如:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回锯齿形层次遍历如下:
[
[3],
[20,9],
[15,7]
]
res=[]
if not root:return res
temp=collections.deque([root])
j=0 # 多设置一个j用来翻转
while temp:
j+=1 #
N=len(temp)
r=[]
for i in range(N):
p=temp.popleft()
r.append(p.val)
if p.left:
temp.append(p.left)
if p.right:
temp.append(p.right)
if j%2: #多了这一步
res.append(r)
else:
res.append(r[::-1])
return res
530. 二叉搜索树的最小绝对差
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
示例:
输入:
1
\
3
/
2
输出:
1
res=[float('inf'),float('-inf')] # 直接中序遍历 , res[1]代表pre的值前一个节点的值 res[0]代表差值
def m(root):
if not root:
return
m(root.left)
res[0]=min(res[0],root.val-res[1])
res[1]=root.val
m(root.right)
m(root)
return res[0]