二叉树_题目19:1367. 二叉树中的链表

68 阅读3分钟

题目19:1367. 二叉树中的链表

1367. 二叉树中的链表

同类题目

前置知识

题目描述

给你一棵以 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
  • 链表包含的节点数目在 1100 之间。
  • 二叉树包含的节点数目在 12500 之间。

思路分析

双重深度优先遍历

树中每一个节点都作为 首节点 去匹配链表的 首节点, 只要有一次匹配成功就返回true

匹配规则

  • 链表到头了head == nullptr,说明已经把链表元素全部匹配了,返回true
  • 链表还没到末尾,树已经到头了root == nullptr,返回false
  • 当前链表元素值与当前树节点元素值不相等root->val != head->val,返回false

程序代码

方法一

 //https://leetcode.cn/problems/linked-list-in-binary-tree/
 //1367. 二叉树中的链表
 #include<iostream>
 using namespace std;
 ​
 struct ListNode {
     int val;
     ListNode *next;
     ListNode() : val(0), next(nullptr) {}
     ListNode(int x) : val(x), next(nullptr) {}
     ListNode(int x, ListNode *next) : val(x), next(next) {}
 };
 ​
 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 };
 ​
 ​
 class Solution {
 public:
     bool travel(ListNode* head, TreeNode* root)
     {
         // 说明比对到链表的最后了
         if(head == nullptr)
         {
             return true;
         }
         // 说明树到低了还没有匹配完链表
         if(root == nullptr)
         {
             return false;
         }
 ​
         bool lv = false;
         bool rv = false;
         
         if(root->val == head->val)
         {
             lv = travel(head->next,root->left);
             rv = travel(head->next,root->right);
         }
         return lv || rv;
     }
 ​
     bool dfs(ListNode* head, TreeNode* root)
     {
         if(root == nullptr)
         {
             return false;
         }
         // 树的所有节点都和链表进行匹配,只要有一个成功即可
         return travel(head,root) || dfs(head,root->left) || dfs(head,root->right);
         
     }
 ​
     bool isSubPath(ListNode* head, TreeNode* root) {
         return dfs(head,root);
     }
 };

复杂度分析

时间复杂度:最坏情况下需要对所有节点进行匹配。假设一共有 n个节点,最坏情况下每次匹配均为到链表的最后一个节点的时候匹配失败,那么一共被匹配到的节点数为2^(len+1)-1 ,即这个节点为根的子树往下len层的满二叉树的节点数,其中len为链表的长度,而二叉树总节点数最多n个,所以枚举节点最多匹配min(2^(len+1),n)次,最坏情况下需要O(n∗min(2^(len+1),n))的时间复杂度。

空间复杂度O(logN) ,其中logN 为二叉树的高度。

题目感悟

双重dfs 第一次使用,不是很熟练,后续会重点练习一下。

更多相关知识:github.com/pingguo1987…