2023-05-10:给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表
如果在二叉树中,存在一条一直向下的路径
且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,那么请你返回 True
(资料图)
否则返回 False 。
一直向下的路径的意思是:从树中某个节点开始,一直连续向下的路径。
输入:head = [4,2,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]。
输出:true。
答案2023-05-10:
大体步骤如下:1.确定链表的长度和节点值序列。遍历链表,记录链表长度 n,并将链表节点值存储到一个整型数组 match 中。
2.利用节点值序列 match 构造 KMP 算法中的 next 数组。next 数组是为了在匹配过程中能够快速跳过与前面已匹配部分不相等的情况。
3.将 head 和 root 传入 isSubPath
函数中计算是否存在一条向下连续的路径恰好对应着链表中每个节点的值。首先搜索左子树,将节点值序列、next 数组以及当前已匹配节点数 mi 作为参数传入 find 函数中进行搜索,若在左子树中找到解则返回 true,否则再在右子树中进行搜索,直到搜索完整棵树。
4.在 find 函数中,若 mi == len(match),表示已经匹配完整个链表,则返回 true;若 cur == nil,表示二叉树中已没有可匹配的节点,返回 false。否则,将当前节点的值与链表中未匹配部分的第一个节点值比较,如果相等则继续往下递归,mi + 1 表示已经匹配的节点数要加 1,否则利用 next 数组回溯 mi 的值,继续比较。直到递归结束返回 true 或 false。
时间复杂度:假设链表中的节点数为 n,二叉树的节点数为 m,则构造 next 数组的时间复杂度是 O(n),搜索整个二叉树的时间复杂度是 O(mn)。因此总时间复杂度是 O(mn)。
空间复杂度:除了输入参数以外,算法使用了常数个大小为 n 的数组和常数个递归栈空间。因此空间复杂度是 O(n)。
go完整代码如下:package mainimport "fmt"// Definition for singly-linked list.type ListNode struct {Val intNext *ListNode}// Definition for a binary tree node.type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func isSubPath(head *ListNode, root *TreeNode) bool {n := 0tmp := headfor tmp != nil {n++tmp = tmp.Next}match := make([]int, n)n = 0tmp = headfor tmp != nil {match[n] = tmp.Valn++tmp = tmp.Next}next := getNextArray(match)return find(root, 0, match, next)}func getNextArray(match []int) []int {if len(match) == 1 {return []int{-1}}next := make([]int, len(match))next[0] = -1next[1] = 0i := 2cn := 0for i < len(next) {if match[i-1] == match[cn] {cn++next[i] = cni++} else if cn > 0 {cn = next[cn]} else {next[i] = 0i++}}return next}func find(cur *TreeNode, mi int, match []int, next []int) bool {if mi == len(match) {return true}if cur == nil {return false}curVal := cur.Valfor mi >= 0 && curVal != match[mi] {mi = next[mi]}return find(cur.Left, mi+1, match, next) || find(cur.Right, mi+1, match, next)}func main() {head := &ListNode{Val: 4,Next: &ListNode{Val: 2,Next: &ListNode{Val: 8,Next: nil,},},}root := &TreeNode{Val: 1,Left: &TreeNode{Val: 4,Right: &TreeNode{Val: 2,Left: &TreeNode{Val: 6,Left: nil,Right: nil,},Right: &TreeNode{Val: 8,Left: nil,Right: nil,},},},Right: &TreeNode{Val: 4,Left: &TreeNode{Val: 2,Left: nil,Right: nil,},Right: &TreeNode{Val: 1,Left: &TreeNode{Val: 3,Left: nil,Right: nil,},Right: nil,},},}res := isSubPath(head, root)fmt.Println(res) // output: true}
rust完整代码如下:use std::cell::RefCell;use std::rc::Rc;// Definition for singly-linked list.#[derive(PartialEq, Eq, Clone, Debug)]pub struct ListNode { pub val: i32, pub next: Option>,}impl ListNode { #[inline] fn new(val: i32) -> Self { ListNode { next: None, val } }}// Definition for a binary tree node.#[derive(Debug, PartialEq, Eq)]pub struct TreeNode { pub val: i32, pub left: Option>>, pub right: Option>>,}impl TreeNode { #[inline] pub fn new(val: i32) -> Self { TreeNode { val, left: None, right: None, } }}fn is_sub_path(head: Option>, root: Option>>) -> bool { let mut n = 0; let mut tmp = &head; while let Some(node) = tmp { n += 1; tmp = &node.next; } let mut match_arr = Vec::with_capacity(n); let mut tmp = &head; while let Some(node) = tmp { match_arr.push(node.val); tmp = &node.next; } let next = get_next_array(&match_arr); find(&root, 0, &match_arr, &next)}fn get_next_array(match_arr: &[i32]) -> Vec { if match_arr.len() == 1 { return vec![-1]; } let mut next = vec![0; match_arr.len()]; next[0] = -1; next[1] = 0; let mut i = 2; let mut cn = 0; while i < next.len() { if match_arr[i - 1] == match_arr[cn as usize] { cn += 1; next[i] = cn; i += 1; } else if cn > 0 { cn = next[cn as usize]; } else { next[i] = 0; i += 1; } } next}fn find(cur: &Option>>, mi: usize, match_arr: &[i32], next: &[i32]) -> bool { if mi == match_arr.len() { return true; } if cur.is_none() { return false; } let cur = cur.as_ref().unwrap().borrow(); let cur_val = cur.val; let mut mi = mi as i32; while mi >= 0 && cur_val != match_arr[mi as usize] { mi = next[mi as usize]; } find(&cur.left, (mi + 1) as usize, match_arr, next) || find(&cur.right, (mi + 1) as usize, match_arr, next)}fn main() { let head = Some(Box::new(ListNode { val: 4, next: Some(Box::new(ListNode { val: 2, next: Some(Box::new(ListNode { val: 8, next: None })), })), })); let root = Some(Rc::new(RefCell::new(TreeNode { val: 1, left: Some(Rc::new(RefCell::new(TreeNode { val: 4, left: None, right: Some(Rc::new(RefCell::new(TreeNode { val: 2, left: Some(Rc::new(RefCell::new(TreeNode { val: 6, left: None, right: None, }))), right: Some(Rc::new(RefCell::new(TreeNode { val: 8, left: None, right: None, }))), }))), }))), right: Some(Rc::new(RefCell::new(TreeNode { val: 4, left: Some(Rc::new(RefCell::new(TreeNode { val: 2, left: None, right: None, }))), right: Some(Rc::new(RefCell::new(TreeNode { val: 1, left: Some(Rc::new(RefCell::new(TreeNode { val: 3, left: None, right: None, }))), right: None, }))), }))), }))); let res = is_sub_path(head, root); println!("{}", res); }
c语言完整代码如下:#include #include typedef struct ListNode { int val; struct ListNode* next;} ListNode;typedef struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right;} TreeNode;int* getNextArray(int* match, int n) { int* next = (int*)malloc(n * sizeof(int)); if (n == 1) { next[0] = -1; return next; } next[0] = -1; next[1] = 0; int i = 2, cn = 0; while (i < n) { if (match[i - 1] == match[cn]) { next[i++] = ++cn; } else if (cn > 0) { cn = next[cn]; } else { next[i++] = 0; } } return next;}int find(TreeNode* cur, int mi, int* match, int* next, int m) { if (mi == m) { return 1; } if (cur == NULL) { return 0; } int curVal = cur->val; while (mi >= 0 && curVal != match[mi]) { mi = next[mi]; } return find(cur->left, mi + 1, match, next, m) || find(cur->right, mi + 1, match, next, m);}int isSubPath(ListNode* head, TreeNode* root) { ListNode* tmp = head; int n = 0; while (tmp != NULL) { n++; tmp = tmp->next; } int* match = (int*)malloc(n * sizeof(int)); tmp = head; int i = 0; while (tmp != NULL) { match[i] = tmp->val; i++; tmp = tmp->next; } int* next = getNextArray(match, n); int res = find(root, 0, match, next, n); free(match); free(next); return res;}ListNode* newListNode(int x) { ListNode* node = (ListNode*)malloc(sizeof(ListNode)); node->val = x; node->next = NULL; return node;}TreeNode* newTreeNode(int x) { TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->val = x; node->left = NULL; node->right = NULL; return node;}int main() { ListNode* head = newListNode(4); head->next = newListNode(2); head->next->next = newListNode(8); TreeNode* root = newTreeNode(1); root->left = newTreeNode(4); root->right = newTreeNode(4); root->left->right = newTreeNode(2); root->right->left = newTreeNode(2); root->left->right->left = newTreeNode(6); root->left->right->right = newTreeNode(8); root->right->left->left = newTreeNode(3); root->right->left->right = NULL; int res = isSubPath(head, root); printf("%d\n", res); free(head->next->next); free(head->next); free(head); free(root->left->right->right); free(root->left->right->left); free(root->left->right); free(root->left); free(root->right->left->left); free(root->right->left); free(root->right); free(root); return 0;}
c++完整代码如下:#include #include using namespace std;struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {}};struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(NULL), right(NULL) {}};vector getNextArray(vector& match) { vector next(match.size(), 0); if (match.size() == 1) { return { -1 }; } next[0] = -1; next[1] = 0; int i = 2; int cn = 0; while (i < match.size()) { if (match[i - 1] == match[cn]) { cn++; next[i] = cn; i++; } else if (cn > 0) { cn = next[cn]; } else { next[i] = 0; i++; } } return next;}bool find(TreeNode* cur, int mi, vector& match, vector& next) { if (mi == match.size()) { return true; } if (cur == NULL) { return false; } int curVal = cur->val; while (mi >= 0 && curVal != match[mi]) { mi = next[mi]; } return find(cur->left, mi + 1, match, next) || find(cur->right, mi + 1, match, next);}bool isSubPath(ListNode* head, TreeNode* root) { ListNode* tmp = head; int n = 0; while (tmp != NULL) { n++; tmp = tmp->next; } vector match(n, 0); tmp = head; int i = 0; while (tmp != NULL) { match[i] = tmp->val; i++; tmp = tmp->next; } vector next = getNextArray(match); return find(root, 0, match, next);}int main() { ListNode* head = new ListNode(4); head->next = new ListNode(2); head->next->next = new ListNode(8); TreeNode* root = new TreeNode(1); root->left = new TreeNode(4); root->right = new TreeNode(4); root->left->right = new TreeNode(2); root->right->left = new TreeNode(2); root->left->right->left = new TreeNode(6); root->left->right->right = new TreeNode(8); root->right->left->left = new TreeNode(3); root->right->left->right = NULL; bool res = isSubPath(head, root); cout << res << endl; return 0;}
标签:
仓储物流“成渝圈”如何乘势而上? 12月3日,连接昆明和万象的中老铁路全线开通运营,被惠及的显...
两件西周青铜簋时隔三千年成功配对 考古工作者介绍,这个铜簋的盖、身分别时隔40余年出土,纹饰...
“医保砍价”不是一个人在战斗 晁星 “我眼泪都快掉下来了”“每一个小群体都不该被放弃”…...
“购物成瘾”真的是一种病 刘艳 牛雅娟 本周日即将迎来“双十二”促销季,很多人又开始摩拳...
因迷恋山间风景,一男子在甘孜州稻城县海拔4000多米的无人区迷失方向,随后与同伴失联。12月的稻城...
嫌疑人DNA信息比中后,成都市公安局刑侦支队技术处DNA实验室民警白小刚一下坐在凳子上,恍惚迟疑间...
一批反映南京大屠杀历史的新书发布 新华社南京12月7日电(记者邱冰清、蒋芳)“以史为鉴,开创未来...
我在现场·照片背后的故事|电影《亲爱的》里面没有的结局,在我眼前“上映” 12月6日,在深圳市...
冥想?泡脚?不如听听助眠音乐 晚上睡不着,白天睡不醒,成为最贴合都市人群的“睡眠画像”。随...
养老话题 老年教育面临缺口 “终身教育”潜力无限 【现实挑战】“新老年”群体愿意在培养兴...
孙海洋被拐14年儿子如何找到的? 警方侦办另一宗拐骗儿童案时发现线索,通过人像比对、DNA确认找...
北京天文馆、圆明园将对未成年人免费开放 12月6日,北京天文馆发布通知称,12月8日起试行对未成...
今年全国粮食总产量再创新高 连续7年保持在1 3万亿斤以上 根据对全国31个省(区、市)的抽样调...
斑块软的很危险 硬的就无碍? 血管里的“垃圾”分类 赶快学起来! 一项最新研究显示:中国...
诺西那生钠注射液大幅降价 聚焦医保谈判背后脊髓性肌萎缩症家庭 医保目录公布那天 好多家长都...
抖音“窗花剪剪”遭抄袭 被判获赔20万元 法院认为“窗花剪剪”的这种表达方式理应受到《著作权...
公安机关近日侦破3起拐卖儿童案件 失散十几年 3组家庭终于团圆了 北京青年报记者12月6日从公...
2021年度十大网络用语发布 本报讯(记者 路艳霞)作为年度“汉语盘点”活动最具网络特色的组成部...
北京天文馆向未成年人免费开放 本报讯(记者 牛伟坤)北京天文馆对票价免费及优惠政策作出调整:1...
2021北京百个网红打卡地发布 本报讯(记者 李洋)2021北京网红打卡地推荐榜单昨晚正式发布。自然...