检查这个问题 - GeeksForgeeks Sum Tree Question 链接
在这个问题中我解决了并且所有主要测试用例都通过了
我的代码如何工作无需在求解函数中传递递归调用的返回值。它正在工作,那么解决递归函数的返回默认值是多少? 有人请解释一下我吗;)
驱动程序代码启动
#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
如果非 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);
}
};