【LetMeFly】1367.二叉树中的链表:深度优先搜索(DFS) - 一步一步实现 力扣题目链接:https://leetcode.cn/problems/linked-list-in-binary-tree/
给你一棵以 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
之间。
解题方法:深度优先搜索DFS 如果我不匹配,只写一个深度优先搜索函数,怎么写?
1 2 3 4 5 6 7 void dfs (TreeNode* t) { if (!t) { return ; } dfs (t->left); dfs (t->right); }
现在还要加上匹配,所以要在dfs的同时返回匹配结果:
1 2 3 4 5 6 7 8 bool dfs (ListNode* l, TreeNode* t) { ... if (dfs (head, t->left) || dfs (head, t->right)) { return true ; } return false ; }
那么到底什么时候会匹配成功,什么时候匹配不成功呢?
如果l
为空,说明链表匹配完了,那不就是匹配成功了吗?返回true
。
如果t
为空,说明二叉树匹配完了,匹配失败,返回false
。
如果l
和t
值相等,那是不是可以尝试匹配列表的下一个值和二叉树的下一个值了?开始递归匹配,若有匹配成功的情况则返回true
。
否则,递归子树节点,从链表头开始,尝试匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 bool dfs (ListNode* l, TreeNode* t) { if (!l) { return true ; } if (!t) { return false ; } if (l->val == t->val) { if (dfs (l->next, t->left) || dfs (l->next, t->right)) { return true ; } } if (dfs (head, t->left) || dfs (head, t->right)) { return true ; } return false ; }
这样真的可以了吗?仔细想想,在“最后的匹配尝试”这一步,我们使用t
的左右子节点和链表的头节点重新进行匹配尝试。这会不会导致重复计算呢?
好像还真会,本来在最初版本递归的时候,就已经会有“二叉树每个节点和链表头节点开始匹配”这一项了。
如果二叉树节点和链表中间某节点匹配失败的时候,是不是就不应该再尝试“子节点从链表头开始匹配”了?
因此,在最后的“最后的匹配尝试”这一步之前应该加上一个特判:l == t
。这样能保证只在“第一次递归”到时重投开始匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 bool dfs (ListNode* l, TreeNode* t) { if (!l) { return true ; } if (!t) { return false ; } if (l->val == t->val) { if (dfs (l->next, t->left) || dfs (l->next, t->right)) { return true ; } } if (l == t) { if (dfs (head, t->left) || dfs (head, t->right)) { return true ; } } return false ; }
你也可以这么理解:
我可以写两个函数:深搜函数(只用来dfs二叉树,用二叉树的每个节点尝试和链表头节点开始匹配)、匹配函数(给定了二叉树节点和链表中的节点位置,只硬着头皮去匹配,失败了不再从头开始)
现在相当于我把两个函数合并为一个了,因此要判断是第一次递归到这个节点时从头开始匹配。
时间复杂度$O(mn)$,其中$m=size(ListNode), n=size(TreeNode)$
空间复杂度$O(n)$
AC代码 C++ - 人类友好版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution {private : ListNode* head; bool dfs (ListNode* l, TreeNode* t) { if (!l) { return true ; } if (!t) { return false ; } if (l->val == t->val) { if (dfs (l->next, t->left) || dfs (l->next, t->right)) { return true ; } } if (l == head) { if (dfs (l, t->left) || dfs (l, t->right)) { return true ; } } return false ; }public : bool isSubPath (ListNode* head, TreeNode* root) { this ->head = head; return dfs (head, root); } };
C++ - 简写版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {private : bool dfs (ListNode* head, ListNode* l, TreeNode* t) { if (!l) { return true ; } if (!t) { return false ; } return l->val == t->val && (dfs (head, l->next, t->left) || dfs (head, l->next, t->right)) || head == l && (dfs (head, l, t->left) || dfs (head, l, t->right)); }public : bool isSubPath (ListNode* head, TreeNode* root) { return dfs (head, head, root); } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from typing import Optional class ListNode : def __init__ (self, val=0 , next =None ): self .val = val self .next = next class TreeNode : def __init__ (self, val=0 , left=None , right=None ): self .val = val self .left = left self .right = rightclass Solution : def dfs (self, l: Optional [ListNode], r: Optional [TreeNode] ) -> bool : if not l: return True if not r: return False if l.val == r.val: if self .dfs(l.next , r.left) or self .dfs(l.next , r.right): return True if l == self .head: if self .dfs(l, r.left) or self .dfs(l, r.right): return True return False def isSubPath (self, head: Optional [ListNode], root: Optional [TreeNode] ) -> bool : self .head = head return self .dfs(head, root)
同步发文于CSDN和我的个人博客 ,原创不易,转载经作者同意后请附上原文链接 哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/144826418