代码随线录刷题Day39
找树左下角的值
这道题,找树左下角的值,受到前一天做过的,找所有从根节点到叶子节点路径的启发,这里可以除了使用一个栈结构辅助深度遍历,还需要使用一个栈记录节点的深度。
先序遍历(因为这样可以保证同一层高度的节点,左节点会比右节点先被遍历到),遍历到叶子节点,先查看该节点的深度是否是当前所有遍历过的节点里最深的,如果是,就记录下该节点(后续如果叶子节点还是这样的高度,无需记录,只需要记录第一次遇到这个高度的节点)。所以这道题必须是严格的先序遍历的右节点先入栈,接着才是左节点再入栈。
代码:
class Solution {
public:int findBottomLeftValue(TreeNode* root) {stack<TreeNode*> treeStack;stack<int> depthStack;int max_val = root->val;int max_depth = 0;TreeNode * tmp_top_ptr;int top_depth = 0;//至少有一个节点,无需判空treeStack.push(root);depthStack.push(1);//迭代遍历,深度遍历节点while(!treeStack.empty()){tmp_top_ptr = treeStack.top(),treeStack.pop();top_depth = depthStack.top();depthStack.pop();//深度最大的,选取第一个深度最大的值if(tmp_top_ptr->left==nullptr && tmp_top_ptr->right ==nullptr){if(top_depth>max_depth){max_val = tmp_top_ptr->val;max_depth = top_depth;continue;}}//孩子节点入栈if(tmp_top_ptr->right){treeStack.push(tmp_top_ptr->right);depthStack.push(top_depth+1);}if(tmp_top_ptr->left){treeStack.push(tmp_top_ptr->left);depthStack.push(top_depth+1);}}return max_val;}
};
这道题,我第一次做的时候,思维太拘泥于题目的字面意思,只考虑左孩子节点,导致56/79的通过率,卡我的例子如下:
这我才反应过来,题目说的最底层最左的节点的含义,是最底层(深度最深)的情况下,然后才是最左的叶子节点,而不是最左的叶子节点中的最深的那个。
路径总和
这道题继续沿用前面的额外使用一个栈来维护从根节点到当前遍历节点的某种信息,这里是用来记录从根节点到当前遍历节点的和。具体代码如下:
class Solution {
public:bool hasPathSum(TreeNode* root, int targetSum) {//深度优先搜索stack<TreeNode*> treeStack;//使用一个栈记录深度遍历时候,根节点到对应节点的节点之和stack<int> sumStack;TreeNode* tmp_node;int top_sum ;//初始化,查空if(root ==nullptr) return false;treeStack.push(root);sumStack.push(root->val);while(!treeStack.empty()){//遍历遇到叶子节点时,查看当前的和是否是目标值,如果是,则返回true,否则继续遍历tmp_node = treeStack.top();treeStack.pop();top_sum = sumStack.top();sumStack.pop();if(tmp_node->left ==nullptr && tmp_node->right ==nullptr){if(top_sum == targetSum) return true;continue;}if(tmp_node->right){treeStack.push(tmp_node->right);sumStack.push(top_sum+tmp_node->right->val);}if(tmp_node->left){treeStack.push(tmp_node->left);sumStack.push(top_sum + tmp_node->left->val);}}return false;}
};
做了这几道题,大致可以感受出来,对于这样的分析从根节点到当前节点的题目,可以使用一个额外的栈,和遍历使用的栈对应起来,记录对应节点的信息。