【问题标题】:LeetCode 236. Lowest Common Ancestor of a Binary Tree C++ solution cannot get expected resultLeetCode 236. Lowest Common Ancestor of a Binary Tree C++ 解法得不到预期的结果
【发布时间】:2023-02-08 17:27:13
【问题描述】:

这是LeetCode第236题Lowest Common Ancestor of a Binary Tree。我对为什么我的 C++ 解决方案无法获得预期结果感到困惑。逻辑运行良好,我假设我对 C++ 语言有一些误解。

当我以这种方式编写代码时,一切都很好:

class Solution {    
private:
    TreeNode* ans;
public:
    bool contain(TreeNode* root, TreeNode* p, TreeNode* q){
        if(root == nullptr){
            return false;
        }
        bool left;
        bool mid;
        bool right;
        mid = (root == p) || (root == q);
        left = contain(root->left,p,q);
        right = contain(root->right,p,q);
        if((mid && left) || (mid && right) || (left && right)){
            ans = root;
            return true;
        }
        return mid || left || right;
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        contain(root,p,q);
        return ans;
    }
};

回答变量可以通过我的辅助函数 contain() 更新,我可以获得正确的结果。 但是,如果我通过回答变量作为参数,那么它永远不会更新并且回答在我调用我的 contain() 助手后,变量仍然为 null。

class Solution {    
public:
    bool contain(TreeNode* root, TreeNode* p, TreeNode* q,TreeNode* ans){
        if(root == nullptr){
            return false;
        }
        bool left;
        bool mid;
        bool right;
        mid = (root == p) || (root == q);
        left = contain(root->left,p,q,ans);
        right = contain(root->right,p,q,ans);
        if((mid && left) || (mid && right) || (left && right)){
            ans = root;
            return true;
        }
        return mid || left || right;
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* ans;
        contain(root,p,q,ans);
        return ans;
    }
};

逻辑是一样的,只是处理方式不同回答变量不同。我不知道为什么在第二种方法中回答辅助函数 contain() 无法成功更新变量。谢谢。

我想我很清楚 C 指针的工作原理,但我的解决方案表明我的理解可能是错误的。

【问题讨论】:

  • 分配给函数的(非引用)参数在该函数之外没有影响。指针没有什么特别之处。
  • 指针可用于通过引用传递它指向的对象,但指针本身只是另一个变量。如果你想改变指针指向的位置,你也需要通过引用传递指针。
  • 同样的事情:void foo(int a) { a = 42; }
  • “这是 LeetCode 第 236 题”-- 如果您努力创建了一个minimal reproducible example,那么当您遇到此问题时就没有理由提及您正在处理的问题。为一个最小的例如,您应该删除不需要重现问题的内容,在本例中是与问题 236 相关的所有逻辑。将您的函数缩小到 bool contain(TreeNode* root, TreeNode* p, TreeNode* q, TreeNode* ans){ ans = root; } 然后意识到您不需要那么多参数:bool contain(TreeNode* root, TreeNode* ans){ ans = root; } .

标签: c++ pointers recursion parameters


【解决方案1】:

将参数传递给函数时会生成一个副本,除非您通过引用传递它:

 void foo(T);        // value - copy
 void foo(T&);       // reference - no copy
 voif foo(const T&); // const reference - no copy

指针也不例外(即当T == U* 时,除非是U*&,否则也会生成一个副本)。

您可能将它与修改指针混淆,如

void bar(int* x) { 
    if(x) *x = 42;
}

但是,bar 不会修改 x。它取消引用 x 以修改其他一些对象。从概念上讲,这类似于

std::vector<int> v(42);
void silly_example_for_illustration(size_t i) {
     v[i] = 42;
}

正如这里对 i 的任何修改都不会在函数外部可见,bar 可以尽可能多地分配给 x,而不会在 bar 之外产生任何影响。虽然,它是一种间接方式,但该函数通过使用参数作为对要修改的实际对象的“引用”来修改其他内容。

(有时不幸的是,C++ 引用的名称与引用的更一般概念冲突,尤其是在讨论按值传递和按引用传递时。无论如何,可以考虑上面的 x 和这里的 i作为引用应修改的实际对象。但函数不修改“引用”,而是修改所引用的对象。)

【讨论】:

    猜你喜欢
    • 2011-12-03
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2022-01-24
    相关资源
    最近更新 更多