首页 > 其他分享 >[LeetCode] 1367. Linked List in Binary Tree 二叉树中的链表

[LeetCode] 1367. Linked List in Binary Tree 二叉树中的链表

时间:2024-08-18 15:27:44浏览次数:13  
标签:Binary head return 结点 链表 二叉树 null root


Given a binary tree root and a linked list with head as the first node.

Return True if all the elements in the linked list starting from the head correspond to some downward path connected in the binary tree otherwise return False.

In this context downward path means a path that starts at some node and goes downwards.

Example 1:

Input: head = [4,2,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
Output: true
Explanation: Nodes in blue form a subpath in the binary Tree.

Example 2:

Input: head = [1,4,2,6], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
Output: true

Example 3:

Input: head = [1,4,2,6,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
Output: false
Explanation: There is no path in the binary tree that contains all the elements of the linked list from head.

Constraints:

  • The number of nodes in the tree will be in the range [1, 2500].
  • The number of nodes in the list will be in the range [1, 100].
  • 1 <= Node.val <= 100 for each node in the linked list and binary tree.

这道题说是给了一棵二叉树,还给了一个链表,问能不能在二叉树中找到一条路径 path,使得其正好是给定的结点链表,题目中例子中的图很好的解释了题意。这里的二叉树的路径并没有限制要从根节点开始,结束位置也不一定要是叶结点,那么理论上不同路径的数量就太多了。如果是想先求出二叉树的所有路径后,再来跟结点链表比较的话,一是太麻烦了,二是效率也不高。最好的办法还是在遍历的过程中就直接开始比较了,比较的方法就是当遇到和此时链表头结点相同的结点时,开始进行下一个结点的比较,由于路径可以去左子结点或者右子结点,所以左右子结点都要去尝试,这里用递归就非常合适了,只要左右子结点任意一个返回 true 了,那么就说明成功匹配了。如果当前的结点和链表头结点的值不相同的话,则分别再去左右子结点进行尝试,此时左右子结点还是跟原来的链表首结点去比较,因为之前没有匹配上,同样,只要左右子结点的递归任意一个返回 true 了,就说明成功匹配上了。根据这种思路写出的代码如下(注意这种下面这种解法是错误的,之后会分析):


// Wrong Solution
class Solution {
public:
    bool isSubPath(ListNode* head, TreeNode* root) {
        if (!head) return true;
        if (!root) return false;
        if (head->val == root->val) {
            return isSubPath(head->next, root->left) || isSubPath(head->next, root->right);
        }
        return isSubPath(head, root->left) || isSubPath(head, root->right);
    }
};

上面的解法虽然简洁,但实际上是错误的解法,这里可以举一个反例:head = [4,2,2], root = [4,2,null,4,null,2],二叉树的结构如下所示:

      4
     /
    2
   /
  4
 /
2

上面解法错误的原因是当 head 匹配完4和2之后,下一个2匹配不上了,因为二叉树中是4,但此时却没有从开头的4重新匹配,而是继续匹配链表中剩下的那个2,这样在跳过二叉树中的第二个4之后,最后一个2就匹配上了,整个就返回了 true。但实际上是错误的,给定的二叉树中并没有一个连续的 4->2->2 路径,相当于找到了类似于字符串中的子序列,而要求的却是子串。正确的做法实际上是对每个结点都当做起始点来匹配一下,这里用一个子函数 dfs 来匹配,匹配的方法就是看链表和二叉树的当前结点值是否相等,是的话再对左右子结点调用递归,只要任意一个返回 true 就行了。在主函数中,调用完 dfs 后,还要分别对左右子结点调用主函数的递归,这样才能保证把每个结点都当起始点来匹配,才能避免上面那个反例的情况,参见代码如下:


class Solution {
public:
    bool isSubPath(ListNode* head, TreeNode* root) {
        if (!head) return true;
        if (!root) return false;
        return dfs(head, root) || isSubPath(head, root->left) || isSubPath(head, root->right);
    }
    bool dfs(ListNode* head, TreeNode* root) {
        if (!head) return true;
        if (!root) return false;
        return head->val == root->val && (dfs(head->next, root->left) || dfs(head->next, root->right));
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1367


参考资料:

https://leetcode.com/problems/linked-list-in-binary-tree

https://leetcode.com/problems/linked-list-in-binary-tree/solutions/524881/python-recursive-solution-o-n-l-time/

https://leetcode.com/problems/linked-list-in-binary-tree/solutions/524821/c-simple-recursion/


LeetCode All in One 题目讲解汇总(持续更新中...)

标签:Binary,head,return,结点,链表,二叉树,null,root
From: https://www.cnblogs.com/grandyang/p/18365679

相关文章

  • 单链表
    //单链表#include<iostream>usingnamespacestd;constintN=1010;inthead,e[N],ne[N],idx;//初始化voidinit(){ head=-1; idx=0;}//插入voidadd_to_head(intx){ e[idx]=x; ne[idx]=head; head=idx; idx++;}//将x插到下标为k的点的后面voidadd(......
  • leetcode 21.合并两个有序链表
    leetcode21.合并两个有序链表题目描述:将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。迭代法:思路:不断迭代,谁小指向谁publicListNodemergeTwoLists(ListNodelist1,ListNodelist2){if(list1==null){......
  • 二叉树——14.二叉搜索树的最小绝对差
    力扣题目链接给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。解题思路总结中序遍历是一种有效的方法,可以将二叉搜索树节点的值按从小到大的顺序排列。通过将这些值存入一个有序数组后,只需遍历数组,比较相邻元素的差值,即可找到树中任意两......
  • 【数据结构】详细剖析链表,带你实现单链表,双向链表,附链表编程练习题
    目录一.链表1.链表的概念及结构2.单链表的实现2.1单链表节点结构2.2动态申请一个节点2.3单链表打印2.4单链表尾插2.5单链表头插2.6单链表尾删2.7单链表头删2.8单链表查找 2.9单链表在pos后一位插入x2.10单链表删除pos后一位的值2.11单链表销毁 ......
  • 知识改变命运 数据结构【链表面试题】
    1.删除链表中等于给定值val的所有节点。OJ链接publicListNoderemoveElements(ListNodehead,intval){if(head==null){returnnull;}ListNodecur=head.next;ListNodepre=head;while(cur!=null){......
  • 数据结构----链表
    一丶概念     链表又称单链表、链式存储结构,用于存储逻辑关系为“一对一”的数据。      和顺序表不同同,使用链表存储数据,不强制要求数据在内存中集中存储,各个元素可以分散存储在内存中。二丶特点     特点:内存不连续,通过指针进行连接 ......
  • 二叉树进阶之二叉搜索树:一切的根源
    前言:在学完了简单的容器与C++面向对象的三大特性之后,我们首先接触的就是map与set两大容器,但是这两个容器底层实现的原理是什么呢?我们不而知,今天,主要来为学习map与set的底层原理而打好基础,而二叉搜索树,则是一切的开端......一、二叉搜索树的定义与性质1.1、什么是二叉搜索树:......
  • 双向链表 尾节点插入
    importlombok.Data;publicclassT{publicstaticvoidmain(String[]args){DoubleLinkedListlist=newDoubleLinkedList();list.addTail(1);list.addTail(2);list.addTail(3);System.out.println("......
  • c语言计算二叉树的带权路径长度之和(WPL)
    1.WPL:树中全部叶节点的带权路径之和2.代码中所画的树为:3.求上述WPL:WPL=0*1+1*2+1*3+2*4+2*5=234.主要代码为:intwpl(Node*ROOT,inthigh){ intn=0; if(ROOT!=NULL){ n=ROOT->weight*high; n=n+wpl(ROOT->lchild,high+1); n=n+wpl(ROOT->rchild,high+1); } r......
  • 数据结构中的双向链表
    1.链表的分类链表的结构非常多样,以下情况组合起来就是8种(2x2x2)链表结构:  在带头链表中,除了头结点,其他结点均存储有效的数据。头结点是占位子的,也叫做“哨兵位”。head结点就是头结点。 循环的链表尾结点不为NULL,不循环的链表尾结点为NULL单链表:不带头单向不循环链......