每日一题2023.9.25|LeetCode1367.二叉树中的链表

1367.二叉树中的链表

链接:LeetCode1367.二叉树中的链表

错误分析

其实这道题目思路很简单:
采用前序遍历的方式从根节点开始遍历二叉树,并在遍历的过程中比较与链表节点的值是否相等,如果当前链表节点的值和树节点的值相等,就在树节点的左右子树寻找下一个链表节点;如果不相等就在树节点的左右子树寻找当前链表节点的值;以下是根据这个思想写出的第一版代码:

/**
 * Definition for singly-linked list.
 * 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) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * 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 isSubPath(ListNode* head, TreeNode* root) {
        return backtracking(head,root);
    }
private:
    bool backtracking(ListNode*head,TreeNode *root){
        if(!head) return true;
        if(!root) return false;
        if(root->val==head->val){
            head=head->next;
        }
        if(backtracking(head,root->left)) return true;
        return backtracking(head,root->right);
    }
};

这个代码只能通过61/67的测试案例
每日一题2023.9.25|LeetCode1367.二叉树中的链表_第1张图片
其实我一开始检查代码的时候并没有发现有什么错误,感觉很符合逻辑,实在不明白哪里出错了。
后来我发现,我传递的参数是以指针的形式传递的,如果当前的链表节点的值与树节点的值相等,会做这么一个操作

if(head->val==root->val) head=head->next;

然后再将这个head传递给下一次递归,这个过程无意当中修改了链表中节点的指向,也就是无意中修改了链表的结构,所以针对某些案例得到了错误的答案。

后来我再次回想这版错误答案的时候,我发现错误之处并非像上述所说的那样,链表的结构不会因为传递的参数而被改变,就像遍历二叉树的时候,树的结构不会因为传递的参数而发生变化。

错误之处应该是:举个例子来说
假设链表的结构为4,2,1;树中包含链表路径的一个分支结构为4,2,8;当head指向1并且root指向8的时候,1!=8,此时会执行以下代码

  if(backtracking(head,root->left)) return true;

这行代码的意思就是,在root[8]的左子树寻找以head[1]为头结点的链表,这个操作把链表进行了分割,所以导致结果错误。

正确解答

为了避免上述的错误,应该在遇到链表节点的值和当前树节点的值不相等的时候,就立马返回false。
在isSubPath()这个函数中,重新用树节点的左右子树与链表头结点进行匹配

/**
 * Definition for singly-linked list.
 * 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) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * 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 isSubPath(ListNode* head, TreeNode* root) {
        if(!head) return true;
        if(!root) return false;
        //这个isSubPath之所以出现在||的后面是因为要找到当一个与head头匹配的root节点从当前位置开始向下寻找
        return backtracking(head,root) ||isSubPath(head,root->left)||isSubPath(head,root->right);
    }
private:
    bool backtracking(ListNode*head,TreeNode *root){
        if(!head) return true;
        if(!root) return false;
        if(root->val!=head->val) return false;
        return backtracking(head->next,root->left) || backtracking(head->next,root->right);

    }
};

你可能感兴趣的:(每日一题,链表,数据结构,c++,算法,二叉树,递归)