这段代码正在解决 Tree Sum 问题,而无需在递归函数中执行 return 语句?

问题描述 投票:0回答:1

我正在尝试解决 GeeksforGeeks 问题 Sum Tree:

给定一棵二叉树。如果对于树中除叶子之外的每个节点 X,其值等于其左子树值与其右子树值之和,则返回 true。否则返回 false

空树也是 Sum Tree,因为空树的和可以被认为是 0。叶子节点也被认为是 Sum Tree。

示例1:

输入:

    3
  /   \    
 1     2

输出: 1

说明: 左子树和右子树的和是 1 + 2 = 3,即根节点的值。 因此,给定的二叉树是一棵和树。

示例2:

输入:

       10
     /    \
   20      30
  /  \ 
10    10

输出:0

说明: 给定的树不是求和树。 对于根节点,元素之和 左子树为 40,元素之和 右子树为 30。根元素 = 10 不等于 30+40。

我下面的代码通过了所有主要测试用例,例如:

  1. 测试用例1:1
  2. 测试用例 2:62 16 15 N 8 4 7 N 8 4
  3. 测试用例 3:110 30 30 10 10 20 10

我的问题

我的代码怎么可能在 return

 函数的递归调用中执行 
solve 语句
而正常工作?看起来递归函数有一个默认返回值
solve
我可以信赖。

代码

这是来自 GeeksforGeeks 的驱动程序代码(不是我的——我只是提供完整信息):

#include <bits/stdc++.h> using namespace std; struct Node { int data; struct Node *left; struct Node *right; }; // Utility function to create a new Tree Node Node* newNode(int val) { Node* temp = new Node; temp->data = val; temp->left = NULL; temp->right = NULL; return temp; } // Function to Build Tree Node* buildTree(string str) { // Corner Case if(str.length() == 0 || str[0] == 'N') return NULL; // Creating vector of strings from input // string after spliting by space vector<string> ip; istringstream iss(str); for(string str; iss >> str; ) ip.push_back(str); // Create the root of the tree Node* root = newNode(stoi(ip[0])); // Push the root to the queue queue<Node*> queue; queue.push(root); // Starting from the second element int i = 1; while(!queue.empty() && i < ip.size()) { // Get and remove the front of the queue Node* currNode = queue.front(); queue.pop(); // Get the current node's value from the string string currVal = ip[i]; // If the left child is not null if(currVal != "N") { // Create the left child for the current node currNode->left = newNode(stoi(currVal)); // Push it to the queue queue.push(currNode->left); } // For the right child i++; if(i >= ip.size()) break; currVal = ip[i]; // If the right child is not null if(currVal != "N") { // Create the right child for the current node currNode->right = newNode(stoi(currVal)); // Push it to the queue queue.push(currNode->right); } i++; } return root; } // } Driver Code Ends // Solution class comes here // ... see my code in next code block ... // //{ Driver Code Starts. int main() { int t; scanf("%d ",&t); while(t--) { string s; getline(cin,s); Node* root = buildTree(s); Solution ob; cout <<ob.isSumTree(root) << endl; } return 1; } // } Driver Code Ends
我的代码:

class Solution { public: // int returnSum=0; // Should return true if tree is Sum Tree, else false int solve(Node* root, int& sumofSubtree){ if(root==NULL){ return 0; } int l = solve(root->left, sumofSubtree); int r = solve(root->right, sumofSubtree); // int sum = l+r; sumofSubtree = l+r+root->data; if(sumofSubtree-root->data == root->data){ return sumofSubtree; } } bool isSumTree(Node* root) { //Main Function int sumofSubtree = 0; solve(root, sumofSubtree); cout<<"sumofSubtree"<<" : "<<sumofSubtree<<endl; // if(sumofSubtree-root->data==root->data || sumofSubtree == root->data){ return true; } else{ return false; } } };
    
tree binary binary-tree binary-search-tree dsa
1个回答
0
投票
如果非 void 函数不返回值,则存在

未定义的行为。尽管它可能适用于多次运行和输入,但这并不可靠。

您的代码当然不会通过每个输入。例如,我在 GeeksforGeeks 用户界面中使用了这个自定义输入测试用例:

3 1 2 4
...测试失败了。

isSumTree

函数给出了函数返回 true 的两种可能性:

  • sumofSubtree - root->data == root->data
  • sumofSubtree == root->data
    
    
这没有什么意义,因为显然

root-data 只有 一个

 正确值,而不是两个。

其他一些备注:

  • 虽然

    sumofSubtree

     是通过引用传递的,但调用者(
    isSumTree
     除外)永远不会使用在进行递归调用后可能已存储在那里的值。它立即覆盖它。所以本质上,这个引用参数仅用于检查根节点。这并没有真正提高代码的可读性。

  • 遍历所有树,而对于某些输入,对前几个节点的检查可能已经表明它不正确。以这棵潜在的大树为例:

    100 / \ 20 20 / \ / \ 5 5 5 5 / \ / \ / \ / \ .. .. .. .. .. .. ..
    
    
无需查看更深层次中的任何节点,就已经很清楚,如果这两个 20 值正确匹配所需的总和并且不是叶子,那么根的值应该是 80,而不是 100。我们不需要查看更深层次的价值观来了解这一点。这里唯一重要的是,这 20 个节点不是叶子,所以如果我们暂时假设它们的子树总和为 20,那么根的两个子树总和为 40。

当根的子节点之一

一片叶子(那么它不算双倍)时,我们可以有类似的推理,...等等。

这里的代码看起来并不比必要的更深入。当然,如果这棵树恰好整体上是正确的,那么就需要遍历所有节点:

class Solution { private: bool isLeaf(Node *root) { return root && !root->left && !root->right; } int getSum(Node *root) { return !root ? 0 : isLeaf(root) ? root->data : 2 * root->data; } public: bool isSumTree(Node* root) { return !root || isLeaf(root) || root->data == getSum(root->left) + getSum(root->right) && isSumTree(root->left) && isSumTree(root->right); } };
    
© www.soinside.com 2019 - 2024. All rights reserved.