你能帮我看看我的代码在没有递归返回值的情况下是如何运行的吗?这段代码中的返回值是什么?

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

检查这个问题 - GeeksForgeeks Sum Tree Question 链接

在这个问题中我解决了并且所有主要测试用例都通过了

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

我的代码如何工作无需在求解函数中传递递归调用的返回值。它正在工作,那么解决递归函数的返回默认值是多少? 有人请解释一下我吗;)

驱动程序代码启动

#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
/*  Tree node
struct Node
{
    int data;
    Node* left, * right;
}; */

// Should return true if tree is Sum Tree, else false
class Solution
{
    public:
    // int returnSum=0;



  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;
        }
        
     
    }
};

//{ 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
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.