为什么我编写的前序遍历(preorder traversal)代码返回空列表?
问题根因分析
你的代码核心问题是递归调用的目标方法错误,叠加成员变量被反复重置,最终导致你观察到的现象:
- 你在
preOrder遍历方法中递归调用的是入口方法preorderTraversal,而非preOrder本身 - 每次调用
preorderTraversal时,第一行代码list = new ArrayList<Integer>()都会把成员变量list指向一个新的空列表,之前存入的内容会直接被丢弃
测试用例执行流程拆解
你使用的测试用例为[1,null,2,3],我们逐步骤走一遍执行逻辑就能对应上你的输出结果:
第一个print(add之前打印)的输出逻辑
- 首次调用
preorderTraversal(节点1),list被初始化为空列表,调用preOrder(节点1) - 进入
preOrder(节点1),第一个print输出[],节点非空,将1加入list,接下来调用preorderTraversal(节点1的左节点null) - 进入
preorderTraversal(null),第一行将list重置为新的空列表,调用preOrder(null) - 进入
preOrder(null),第一个print输出[],节点为空直接返回 - 回到
preOrder(节点1)的逻辑,调用preorderTraversal(节点1的右节点2) - 进入
preorderTraversal(节点2),第一行将list重置为新的空列表,调用preOrder(节点2) - 进入
preOrder(节点2),第一个print输出[],节点非空,将2加入list,接下来调用preorderTraversal(节点2的左节点3) - 进入
preorderTraversal(节点3),第一行将list重置为新的空列表,调用preOrder(节点3) - 进入
preOrder(节点3),第一个print输出[],节点非空,将3加入list,接下来调用preorderTraversal(节点3的左节点null) - 进入
preorderTraversal(null),第一行将list重置为新的空列表,调用preOrder(null),print输出[]后返回 - 回到
preOrder(节点3),调用preorderTraversal(节点3的右节点null) - 进入
preorderTraversal(null),第一行将list重置为新的空列表,调用preOrder(null),print输出[]后返回
以上流程一共触发7次print,全部输出空列表,和你观察到的结果完全一致。
第二个print(add之后打印)的输出逻辑
print在add操作之后执行,每次add之后还没来得及保留结果,下一次调用preorderTraversal就会把list清空:
- 节点1加入list后print输出
[1],随后调用左节点的preorderTraversal把list清空 - 处理节点2时,
preorderTraversal先清空list,add 2之后print输出[2],随后调用左节点的preorderTraversal把list清空 - 处理节点3时,
preorderTraversal先清空list,add 3之后print输出[3]
所以最终输出三行各只有一个元素的列表,和你观察到的结果一致。
你的认知偏差点
- 你误以为成员变量
list初始化后不会被修改,但实际上你每次递归调用入口方法preorderTraversal时,都会主动给list赋值新的空列表,不是存在多个list对象,是同一个list引用被反复指向了新的空列表对象,旧列表的内容直接被丢弃。 - 你混淆了递归调用的目标:前序遍历的递归逻辑应该直接调用
preOrder处理子节点,入口方法preorderTraversal仅需要调用一次,用来完成初始化操作,不应该作为递归调用的目标。
内容的提问来源于stack exchange,提问作者user
相关产品推荐
相关产品推荐

