Python内存变量中的引用详解
116. 填充每个节点的下一个右侧节点指针
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return
queue = [root]
while queue:
#for i in range(len(queue)):
node = queue.pop(0)
#res.append(node.val). '不需要返回数值?#是数值吗'
if node.next and node.left and node.right:
node.right.next = node.next.left
if node.left and node.right:
node.left.next = node.right
queue.append(node.left)
queue.append(node.right)
return root
疑问2:queue = [root] 存储的是 root 对象的引用(内存地址),而非对象本身,不是节点的值。(当创建一个节点 root 时,Python 会在内存中分配一个对象,并让 root 变量指向这个对象的地址。)queue = [root] # 列表中存储的是指向 Node 对象的指针
Node)等都是对象,每个对象有唯一的内存地址(引用);变量名本质是对象的 “别名”,存储的是对象的内存地址(引用),而非对象的值或副本。
a = 10
print(id(a)) # 输出 a 的内存地址(引用)
class MyClass:
def __init__(self, val):
self.val = val
obj1 = MyClass(10)
obj2 = obj1 # obj2 引用同一对象
obj2.val = 20 # 通过引用修改对象属性
print(obj1.val) # 输出:20(对象本身被修改)
通过id()函数判断,若两个变量id相同,则指向同一对象(引用)
a = [1, 2, 3]
b = a
print(id(a) == id(b)) # 输出:True(同一引用)

本题另外一种解法:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return root
"queue 只是遍历过程中临时使用的辅助工具"
queue = [root]
while queue:
level = len(queue)
for i in range(len(queue)):
node = queue.pop(0)
"这个时候用level固定值,因为len()调用函数会在此时重新计算长度,而已经pop一个"
if i < level - 1:
node.next = queue[0]
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root

111. 二叉树的最小深度
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
"调用递归加上self.函数"
level_left = self.minDepth(root.left)
level_right = self.minDepth(root.right)
"需要判断==0即空节点的特殊情形"
if min(level_left,level_right) == 0:
res = max(level_left,level_right) + 1
else:
res = min(level_left,level_right) + 1
return res
类函数调用&普通函数调用:
函数定义在类的内部,第一个参数是 self 时,它被称为实例方法。
- 通过
self,可以访问类的属性和其他方法。 - 每个实例对象都有自己的属性和方法副本,
self确保递归调用的是当前这个实例的方法。
实例方法必须通过实例对象调用,无法直接通过类名调用(除非使用@classmethod)
# 正确调用方式
sol = Solution()
sol.minDepth(root) "# self 自动绑定到 sol 实例"
# 错误调用方式(缺少实例)
Solution.minDepth(root) # 会报错,缺少 self 参数
若在类外部定义相同的函数,则无需self:
# 类外部的独立函数(无需 self)
def minDepth(root: Optional[TreeNode]) -> int:
if root is None:
return 0
...
226. 翻转二叉树
- 本题错误原因:交换左右孩子,交换的是(引用地址)指针,不是数值
- queue只是辅助把树遍历完的一个工具,而题目是想真正的反转这棵树。如果只改变queue的值不是node并不能真正改变这棵树.
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return None
queue = [root]
while queue:
node = queue.pop(0)
if node.right:
queue.append(node.right)
if node.left:
queue.append(node.left)
node.left, node.right = node.right, node.left
return root
101. 对称二叉树
二叉树写递归,单层递归逻辑(可以用任一层的根节点做模拟),如使用后序遍历处理的逻辑:
递归遍历一个二叉树根root:

同时递归遍历两个树root1 root2:
(root1-left, root2-right)按照node.left一直left到底,按照node.right一直right到底;
root1 = node.left root2 = node.right
(node.left-right, node.right-left)按照node.left一直right到底,按照node.right一直left到底;
递归return,终止递归,返回的是当前层的结果;回溯,逐层返回;(有的需要回溯时候,逐层返回值收集起来;有的只需要把递归走一遍)
没到终止条件,则继续使用函数递归;
现在感觉leetcode解题,就是看谁规律掌握的好?找到一种可行的解法。
找到规律后处理,就是算法,就叫巧妙的解法。
以及对存储结构的了解,【#】是指返回字符串#?
作者:weixin_40879974