遇到的错误和解决方案:
1.函数嵌套函数
2. 调用函数返没有返回值 return
3.函数调用函数中间的参数的传递和全局变量和局部变量的问题
解决:函数的闭包问题
闭:指的是定义在函数内部的函数
注意:作用域关系在函数定义阶段就规定死了,与调用位置无关
闭包函数:定义在函数内部的函数,并且该函数包含对外部函数作用域中名字的引用,该函数就称为闭包函数
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
函数嵌套与闭包函数 - 鲁之敬 - 博客园 (cnblogs.com)
Python闭包函数的使用和原理 - 腾讯云开发者社区-腾讯云 (tencent.com)
def first():
res = []
def second():
res.append(1)
second()
print( res)
first()
#means
def first():
res = []
def second():
res.append(1)
second()
return res
x = first()
print(x)
#第六题
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
#
class Solution:
def printListFromTailToHead(self , listNode: ListNode) -> List[int]:
# write code here
res = []
if not listNode:
print(3)
return res
def traverse(root):
if not root:
return res
# if root.next == None:
# res.append(root.val)
# print(2,res)
# return res //注意:在函数中如果用了上一层函数的变量,nonlocal类型的变量,那就是直接对上一层函数的进行修改,不能用return ,不然只能得到空
if root.next:
traverse(root.next)
res.append(root.val)
print(1,res)
traverse(listNode)
return res //在最后直接输出就好,不用从上面使用 res=traverse(listNode)获得
4.调用函数
不带括号:只是赋值而没有启动函数
带括号:赋值并且函数
def bar():
print('from bar')
f = bar()
# from bar
def bar():
print('from bar')
f = bar
f()
# from bar
def bar():
print('from bar')
f = bar
# 没有输出
带传参
5.TypeError: descriptor 'append' for 'list' objects doesn't apply to a 'int' object
并没有看明白这是啥问题
题目:
五:替换空格: 从后向前看,从末尾一开始计算好要移动的位置
六:从尾到头打印 :
1.利用栈分析 从头到尾把数据加入到栈中,再利用pop输出元素
2.利用递归写
递归类似与栈,栈的深度是一定的,如果数据很多就会超过栈的深度
七:做题老是会遇到一种情况,要保留第一次循环的结果,比如第七题,需要保留root的内容最后输出,(或者构建出树之后在从后往前输出?)
~~~怎么处理每一个节点
~~~怎么处理叶子节点~~
一开始
class Solution:
def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
# write code here
#在pre中找到根节点,然后在vin中根据根节点分成左右子树的vin,再根据分成的左右子树
# 的长度去pre中找同样长度的pre内容
if len(pre) ==0:
return
# if len(pre) == 1 and len(vin) == 1:
# return
root = TreeNode(pre[0])
print(root.val)
# 输出 1 2 3 然后就停止了,证明是遇到第一个叶子节点的时候返回出错
# print(root.val)
root_vinindex = vin.index(pre[0])
# 求左右子树的vin
leftvin = vin[:root_vinindex]
rightvin = vin[root_vinindex+1:]
# 求左右子树的长度
left_length=len(leftvin)
right_length = len(rightvin)
# 求左右子树的pre
leftpre = pre[1:left_length+1]
rightpre = pre[left_length+1:]
print(1,leftpre,2,rightpre)
print(1.1,leftvin,2.2,rightvin)
root.left = TreeNode(leftpre[0])
root.right = TreeNode(rightpre[0])
if len(leftpre)>0:
self.reConstructBinaryTree(leftpre,leftvin)
if len(rightpre)>0:
self.reConstructBinaryTree(rightpre,rightvin)
return root
首先,原本的思路算不出来,但是通过加一个队列,使用层次遍历的方法,每个节点构建字典,对应它自己的前序和中序,最后读取字典,利用层次遍历一层一层的加左右节点,也许能解决?感觉很麻烦
因为列表长度问题,一个列表如果只有list[0]但是你调用了list[1]就会溢出
我不知道怎么来处理这个最后list[0]的 的情况,然后看了大佬的代码,通过直接
root.left = createfunction()构建函数来解决
再通过if not root :return 来限制叶子节点之下的节点,咱就是说这也太牛了吧wwww
换个思路解决问题
class Solution:
def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
# write code here
#在pre中找到根节点,然后在vin中根据根节点分成左右子树的vin,再根据分成的左右子树
# 的长度去pre中找同样长度的pre内容
if not pre:
return
# if len(pre) == 1 and len(vin) == 1:
# return
root = TreeNode(pre[0])
print(root.val)
# 输出 1 2 3 然后就停止了,证明是遇到第一个叶子节点的时候返回出错
# print(root.val)
root_vinindex = vin.index(pre[0])
# 求左右子树的vin
leftvin = vin[:root_vinindex]
rightvin = vin[root_vinindex+1:]
# 求左右子树的长度
left_length=len(leftvin)
right_length = len(rightvin)
# 求左右子树的pre
leftpre = pre[1:left_length+1]
rightpre = pre[left_length+1:]
# print(1,leftpre,2,rightpre)
# print(1.1,leftvin,2.2,rightvin)
# !!!这一步很厉害哇我靠,通过return 和 直接调用函数的方法构造树
root.left = self.reConstructBinaryTree(leftpre,leftvin)
root.right = self.reConstructBinaryTree(rightpre,rightvin)
return root
细想,我的代码和和正确代码最大的区别是
我的代码使用root.left = TreeNode (从子节点前序列表取值构建),是一种从上到下的思想,从上往下把左右节点加到root上
而修改后的代码,是使用递归从下到上的思想,从到达叶子节点的return 开始构建,从下到上 第一层:把叶子节点左右左右节点加到上一层节点,之后的每一层把左右子树加到root节点
发散:在斐波那契数列中也有类似的思想,一开始是从上到下构建数列,然后 第一次修改 利用备忘录记录下可能重读计算的节点,之后再使用到节点的值,第二次修改时想要计算f(n)的斐波那契数列,从下往上计算 f(1)-f(2)---f(n)的方式计算。
发现自己缺:
1.返回值处理的不好
2.循环,递归结束位置处理的不好
第八题:求二叉树的下一个节点
注意:在输入中,看似输入了一个集合和一个Int数字,实则输入一个二叉树和一个节点,只需要直接对节点操作就行,某些时候看似多种情况,列出来还要记得找规律,结合中序遍历的特点
# -*- coding:utf-8 -*-
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None
class Solution:
def GetNext(self, pNode):
# write code here
#思想:在自己找到临界值节点做尝试,找到合适的节点,用实例来找下一个节点
# 选择几个特殊节点:8 -- 9 (有右子树 -- 右子树的最左子节点) 6-7 10-11
# 5 -- 6 (没有右子树,且为父节点的左子节点 -- 头节点) self.next 9-10
# 7 -- 8 (没有右子树,且为父节点的右子节点 -- 某一级父节点是左子节点)
# 11 -- null 树的最右叶子节点 以上三种情况都不是
# 也就是分为 :有右子树 --- 右子树最左节点
# 没有右子树 --- 是父节点的左子节点 --父节点
# 是父节点的右子节点 --找父节点(是左子节点)
if pNode == None:
return None
# 第二步,找每个节点有什么特殊的地方 ,从节点本身的三个指针来看
pNext = None
if pNode.right:
pcurrent = pNode.right
while pcurrent.left:
pcurrent = pcurrent.left
pNext = pcurrent
elif pNode.next:
pcurrent = pNode
pParent = pNode.next
while pParent!=None and pcurrent == pParent.right:
# 如果是右子节点,则进入循环,这个地方相当于把两个情况合并,最终都是要找某个父节点
pcurrent = pParent
pParent = pParent.next
pNext = pParent
return p