leetcode
leetcode 1251 ~ 1300
二叉树中的链表

二叉树中的链表

难度:

标签:

题目描述

给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表。

如果在二叉树中,存在一条一直向下的路径,且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,那么请你返回 True ,否则返回 False

一直向下的路径的意思是:从树中某个节点开始,一直连续向下的路径。

 

示例 1:

输入:head = [4,2,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
输出:true
解释:树中蓝色的节点构成了与链表对应的子路径。

示例 2:

输入:head = [1,4,2,6], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
输出:true

示例 3:

输入:head = [1,4,2,6,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
输出:false
解释:二叉树中不存在一一对应链表的路径。

 

提示:

  • 二叉树和链表中的每个节点的值都满足 1 <= node.val <= 100 。
  • 链表包含的节点数目在 1 到 100 之间。
  • 二叉树包含的节点数目在 1 到 2500 之间。

代码结果

运行时间: 42 ms, 内存: 16.7 MB


// Java Stream solution
// 思路:使用递归和流的组合,找到树中所有匹配链表头的节点并进一步递归检查路径。
public class Solution {
    public boolean isSubPath(ListNode head, TreeNode root) {
        return root != null && (dfs(root, head) || isSubPath(head, root.left) || isSubPath(head, root.right));
    }
    private boolean dfs(TreeNode node, ListNode head) {
        if (head == null) return true;
        if (node == null || node.val != head.val) return false;
        return dfs(node.left, head.next) || dfs(node.right, head.next);
    }
}

解释

方法:

该题解采用了深度优先搜索(DFS)的方式来判断二叉树中是否存在与链表对应的一条向下的路径。首先,题解中构建了一个失败指针(类似于KMP算法中的失配数组)来优化链表节点的比较过程。使用两个栈来模拟递归的过程,一个栈存储当前待比较的二叉树节点,另一个栈存储当前对应的链表节点。遍历二叉树的每个节点,与当前链表节点比较,如果值相同,则向下移动;如果不匹配,则使用失败指针回退到上一个可能的匹配位置。如果链表的所有节点都成功匹配,则返回真;否则,继续检查二叉树的其他路径。

时间复杂度:

O(N + L)

空间复杂度:

O(L + H)

代码细节讲解

🦆
为什么在题解中需要构建链表的失败指针数组,这种方法具体是如何优化比较过程的?
在题解中构建链表的失败指针数组(类似于KMP算法中的失配数组)可以显著优化匹配过程。当在二叉树中搜索与链表对应的路径时,如果遇到不匹配的情况,我们可以使用失败指针数组直接跳过一些无需重新检查的节点,这样可以避免从链表的头部重新开始匹配,从而节省了大量的时间。这种方法减少了重复的比较操作,提高了算法的效率。
🦆
在题解中提到使用两个栈来模拟递归的过程,这种方法与直接使用递归相比有什么优势或不足?
使用两个栈来模拟递归的过程,相比直接使用递归,有一些优势和不足。优势在于更好的控制递归的过程和管理内存使用,因为递归可能导致栈溢出,尤其是在处理非常大的树或深度非常深的递归调用时。不足之处在于代码复杂度较高,可读性和维护难度都可能增加,同时手动管理栈可能引入错误。
🦆
题解中在不匹配的情况下使用失配字典回退到上一个可能的匹配位置,这种处理方式是否可能导致重复访问某些节点,从而影响效率?
是的,使用失配字典回退到上一个可能的匹配位置可能会导致重复访问某些节点。尤其是在二叉树的结构较为复杂,或者链表与树节点的值频繁不匹配的情况下,这种回退机制可能会多次重试相同的节点,从而影响算法的效率。然而,这种方法仍然比完全重新开始匹配来得更有效率。
🦆
题解中提到'如果链表的所有节点都成功匹配,则返回真',请问如果二叉树的某个分支长度小于链表长度,但开始的几个节点是匹配的,这种情况是如何处理的?
如果二叉树的某个分支长度小于链表长度,即使开始的几个节点匹配,最终还是无法完成整个链表的匹配。在这种情况下,一旦二叉树的遍历到达分支末尾但链表尚未完全匹配,算法会停止当前路径的匹配尝试,并回退到上一个分叉点继续尝试其他可能的路径。如果所有可能的路径都无法匹配整个链表,最终结果返回False。

相关问题