Leetcode C++ 二叉树&递归

6 篇文章 0 订阅
5 篇文章 0 订阅

Leetecode 104

104. Maximum Depth of Binary Tree

Given the root of a binary tree, return its maximum depth.
A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

  • 思路:
    递归方法求解。
int maxDepth(TreeNode* root) {
    if (!root)
        return 0;
    return  1 + max(maxDepth(root->left), maxDepth(root->right));
}

Leetecode 111

111. Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.
The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
Note: A leaf is a node with no children.

  • 思路:
    递归方法求解。与leetcode104(求最大深度)相比较需要注意的是当一个节点一边子树为空而另一边子树存在时,为空的子树将不参加计算,而只需要返回另一个非空子树的最小深度。
int minDepth(TreeNode* root) {
    if (!root)
        return 0;
    if (root->left && root->right) // 左右子树都存在
        return 1 + min(minDepth(root->left), minDepth(root->right));
    if (root->left) // 右子树为空,左子树存在
        return 1 + minDepth(root->left);
    else if (root->right) // 右子树存在,左子树为空
        return 1 + minDepth(root->right);
    else // 左右子树都为空
        return 1;
}

第二种实现

int minDepth(TreeNode* root) {
    if (!root)
        return 0;
    int l_depth = INT_MAX; // 当左右子树只有一个为空时,其深度将定义为最大值
    int r_depth = INT_MAX;
    if (!root->left && !root->right) // 终止条件
        return 1;
    if (root->left)
        l_depth = minDepth(root->left);
    if (root->right)
        r_depth = minDepth(root->right);
    return 1 + min(l_depth, r_depth);
}

Leetecode 226

226. Invert Binary Tree

Invert a binary tree.

  • 思路:
    通过递归的方式,实现二叉树的镜像翻转。
void invertTreeCore(TreeNode* root) {
    if (root->left)
        invertTreeCore(root->left);
    if (root->right)
        invertTreeCore(root->right);
    swap(root->left, root->right);
}
TreeNode* invertTree(TreeNode* root) {
    if (!root)
        return root;
    invertTreeCore(root);
    return root;
    
}

Leetecode 100

100. Same Tree

Given the roots of two binary trees p and q, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.

  • 思路:
    判断两棵树是否相同,使用递归方法,首先判断当前节点是否相同:
  1. 如果都为空,那么返回true;
  2. 如果都不空,那么判断值是否相等;
    2.1 如果值相等那么递归判断左子树和右子树是否相同;
    2.2 如果值不相等,那么返回false
  3. 其他情况,说明一个为空,一个不空,那么返回false;
bool isSameTree(TreeNode* p, TreeNode* q) {
    if (!p && !q)
        return true;
    else if (p && q)
        if (p->val == q->val)
            return (isSameTree(p->left, q->left) && isSameTree(p->right, q->right));
    return false;
}

Leetecode 101

101. Symmetric Tree

Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center)…

  • 思路:
    使用递归方法,如果整棵树对称,那么根节点的左右两个子树应该形成对称,所以本质为判断两个树是否为对称。
    这个问题需要注意的地方是递归的终止条件:
  1. 两个节点都为空,那么返回true且终止;
  2. 两个节点一个为空,一个不空那么返回false且终止;
  3. 两个节点都不为空,但是值不相等,那么返回false且终止。
  4. 两个节点都不空且值相等,那么继续递归左右子树。
bool isSubSymmetric(TreeNode* left_root, TreeNode* right_root) {
    // both null
    if (!left_root && !right_root)
        return true;
    // one null, one has
    if (!left_root || !right_root)
        return false;
    // both have but not equal
    if (left_root && right_root)
        if (left_root->val != right_root->val)
            return false;
    return (isSubSymmetric(left_root->left, right_root->right) && 
            isSubSymmetric(left_root->right, right_root->left));
}
bool isSymmetric(TreeNode* root) {
    if (!root)
        return true;
    return isSubSymmetric(root->left, root->right);
}

Leetecode 222

222. Count Complete Tree Nodes

  • 思路:
    计算一颗完全二叉树的总节点数,思路类似与leetcode104,直接使用递归的方法。
int countNodes(TreeNode* root) {
   if (!root)
       return 0;
    return 1 + countNodes(root->left) + countNodes(root->right);
}

Leetecode 110

110. Balanced Binary Tree

Given a binary tree, determine if it is height-balanced.
For this problem, a height-balanced binary tree is defined as:
a binary tree in which the left and right subtrees of every node differ in height by no more than 1.

  • 思路:
    使用递归求树的高度的思路,在求高度的同时,判断左右子树的高度差是否大于1,如果大于1那么设置返回值为false。
bool res = true;
int treeHeight(TreeNode* root) {
    if (!root)
        return 0;
    int left_height = treeHeight(root->left);
    int right_height = treeHeight(root->right);
    if (abs(left_height - right_height) > 1)
        res = false;
    return 1 + max(left_height, right_height);
}
bool isBalanced(TreeNode* root) {
    treeHeight(root);
    return res;

Leetecode 112

112. Path Sum

Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.
A leaf is a node with no children.

  • 思路:
    使用递归方法,转换为分别求root的左右子树问题,此时targetSum为减掉root->val后的值,当到叶子节点时,判断targetSum与该叶子节点之差是否为0。
    注意:只有到达叶子节点时才开始判断,对于只有一边有子树的节点,对于没有子树的一边默认返回false即可。
// 写法1;
bool hasPathSum(TreeNode* root, int targetSum) {
    if (!root)
        return false;
    if (!root->left && !root->right) {
        if (targetSum == root->val)
            return true;
        else 
            return false;
    }
    bool left = false; // 单边情况,没有子树的一边默认为false
    bool right = false;
    if (root->left)
        left = hasPathSum(root->left, targetSum - root->val);
    if (root->right)
        right = hasPathSum(root->right, targetSum - root->val);
    return left || right;            
}

// 写法2:
bool hasPathSum(TreeNode* root, int targetSum) {
    if (!root) // 如果根为空或者只有单边的情况,返回false
        return false;
    if (!root->left && !root->right) { // 到达叶子节点
        if (targetSum == root->val)
            return true;
        else 
            return false;
    }
    return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);        
}

Leetecode 404

404. Sum of Left Leaves

Find the sum of all left leaves in a given binary tree…

  • 思路:
    求一个树的所有左叶子节点的和。该问题可以首DFS或BFS寻找所有的做叶子节点,然后求和。同时也
    可以使用递归的方法解决。
    • 实现1
      使用辅助函数,记录当前递归到的节点是否为左节点,再次基础上判断是否为叶子节点。
int sumOfLeftLeavesCore(TreeNode* root, bool is_left) {
    if (!root)
        return 0;
    if (!root->left && !root->right) {
        if (is_left)
            return root->val;
        else 
            return 0;
    }
    return sumOfLeftLeavesCore(root->left, true) + sumOfLeftLeavesCore(root->right, false);
}
int sumOfLeftLeaves(TreeNode* root) {
    if (!root)
        return 0;
    return sumOfLeftLeavesCore(root->left, true) + sumOfLeftLeavesCore(root->right, false);
}
  • 实现2
    直接在递归中判断当前节点的左节点是否为叶子节点。
int sumOfLeftLeaves(TreeNode* root) {
    if (!root)
        return 0;
    if (root->left && !root->left->left && !root->left->right)
        return root->left->val + sumOfLeftLeaves(root->right);
    return sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}

Leetecode 257

257. Binary Tree Paths

Given the root of a binary tree, return all root-to-leaf paths in any order.

  • 思路:
    本质时二叉树的深度优先遍历。到达叶子节点时输出从根到叶子节点的路径。可以使用递归和迭代两种方法解决。
// 1. 递归方法
void binaryTreePathsCore(TreeNode* root, vector<int>& nums, vector<string>& res){
    nums.push_back(root->val);
    if (!root->left && !root->right) {
        string str;
        for (int i = 0; i < nums.size(); ++ i) {
            str += to_string(nums[i]);
            if (i < (nums.size() - 1))
                str += "->";
        }
        res.push_back(str);
        nums.pop_back();
        return;
    }
    
    if (root->left)
        binaryTreePathsCore(root->left, nums, res);
    if (root->right)
        binaryTreePathsCore(root->right, nums, res);
    nums.pop_back();
}
vector<string> binaryTreePaths(TreeNode* root) {
    vector<string> res;
    if (!root)
        return res;
    vector<int> nums;
    binaryTreePathsCore(root, nums, res);
    return res;
}

// 2. 迭代方法(基于后序遍历的DFS):
vector<string> binaryTreePaths(TreeNode* root) {
    vector<string> res;
    if (!root)
        return res;
    stack<TreeNode*> stk;
    TreeNode* node = root;
    TreeNode* last;
    vector<int> nums;
    while (node || !stk.empty()) {
        if(node) {
            stk.push(node);
            nums.push_back(node->val);
            node = node->left;
        } else {
            node = stk.top();
            if (node->right && last != node->right) {
                node = node->right;
            } else {
                if (!node->left && !node->right) {
                    string str;
                    for (int i = 0; i < nums.size(); ++ i) {
                        str += to_string(nums[i]);
                        if (i < (nums.size() - 1))
                            str += "->";
                    }
                    res.push_back(str);
                }
                stk.pop();
                nums.pop_back();
                last = node;
                node = nullptr;
            }
        }
    }
    return res;
}

Leetecode 113

113. Path Sum II

Given the root of a binary tree and an integer targetSum, return all root-to-leaf paths where each path’s sum equals targetSum.
A leaf is a node with no children.

  • 思路:
    本质是二叉树的深度优先遍历,返回所有和为targetSum的节点路径。可以通过递归和迭代两种方法,其中迭代方法是由后续遍历即可。
  1. 递归方法
    每次递归需要将targetSum减去当前节点的val。
// all root must NOT be nullptr;
void pathSumCore(TreeNode* root, int targetSum, 
                 vector<int>& ints, vector<vector<int> >& res) {
    ints.push_back(root->val);
    if (!root->left && !root->right) { // 到达叶子节点
        if (targetSum == root->val) { // 和满足要求
            res.push_back(ints);
        } 
        ints.pop_back();
        return;
    }
    if (root->left) 
        pathSumCore(root->left, targetSum - root->val, ints, res); // 注意targetSum的改变
    if (root->right)
        pathSumCore(root->right, targetSum - root->val, ints, res);
    ints.pop_back();
}

vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
    vector<vector<int> > res;
    if (!root)
        return res;
    vector<int> ints;
    pathSumCore(root, targetSum, ints, res);
    return res;
}
  1. 迭代方法
    基于后续遍历的DFS,要注意在迭代过程中targetSum要减去当前节点val,同时在stack中有pop的时候要将targetSum的值恢复。
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
    vector<vector<int> > res;
    if (!root)
        return res;
    TreeNode* node = root;
    TreeNode* last = nullptr;
    stack<TreeNode*> stk;
    vector<int> nums;
    while (node || !stk.empty()) {
        if (node) {
            stk.push(node);
            nums.push_back(node->val);
            targetSum -= node->val; // 注意targetSum的变化
            node = node->left;
        } else {
            node = stk.top();
            if (node->right && last != node->right) {
                node = node->right;
            } else {
                if (!node->left && !node->right && targetSum == 0) { // 到达叶子节点且targetSum为0
                    res.push_back(nums); // 记录
                }
                stk.pop();
                nums.pop_back();
                targetSum += node->val; // 注意targetSum的变化(恢复)
                last = node;
                node = nullptr;
            }
        
        }
    }
    return res;
}

Leetecode 129

129. Sum Root to Leaf Numbers

You are given the root of a binary tree containing digits from 0 to 9 only.
Each root-to-leaf path in the tree represents a number.
For example, the root-to-leaf path 1 -> 2 -> 3 represents the number 123.
Return the total sum of all root-to-leaf numbers.
A leaf node is a node with no children.

  • 思路:
    二叉树中假设从root到leaf的节点组成一个整数,然后求所有这些整数的和。
    解题思路是递归的思路,整数的构造方法为root到父节点所代表的整数* 10 + 当前节点,从而形成递归,属于二叉树的DFS,实现方式有两种,分别是递归和迭代。
    需要注意的是变量的还原。
  1. 递归方法:
// recurrent
void sumNumbersCore(TreeNode* root, int& sub_sum, int& sum) {
    sub_sum = 10 * sub_sum + root->val; // root到父节点所代表的整数* 10 + 当前节点
    if (!root->left && !root->right) { // leaf node
        sum += sub_sum;
    }
    if (root->left)
        sumNumbersCore(root->left, sub_sum, sum);
    if (root->right)
        sumNumbersCore(root->right, sub_sum, sum);
    sub_sum = (sub_sum - root->val) / 10; // 变量还原
}

int sumNumbers(TreeNode* root) {
    int sum = 0;
    if (!root)
        return sum;
    int sub_sum = 0;
    sumNumbersCore(root, sub_sum, sum);
    return sum;
}
  1. 迭代方法:
int sumNumbers(TreeNode* root) {
    int sum = 0;
    if (!root)
        return sum;
    stack<TreeNode*> stk;
    TreeNode* last = nullptr;
    TreeNode* node = root;
    int sub_sum = 0;
    while (node || !stk.empty()) {
        if (node) {
            stk.push(node);
            sub_sum = 10 * sub_sum + node->val; // root到父节点所代表的整数* 10 + 当前节点 
            node = node->left;
        } else {
            node = stk.top();
            if (node->right && last != node->right) {
                node = node->right;
            } else {
                if (!node->left && !node->right) {
                    sum += sub_sum;
                }
                sub_sum = (sub_sum - node->val) / 10; // 变量还原
                stk.pop();
                last = node;
                node = nullptr;
            }
            
        }
    }
    return sum;
}

Leetecode 437

437. Path Sum III

You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).

  • 思路:
    该问题要求找出二叉树中所有和满足targetSum的路径的数量,该路径的起点和终点都没有要求,因此接替思路为遍历二叉树所有节点,将每个节点都作为起点(终点没有要求)寻找其满足条件的路径数量,然后将路径数量求和。也就是说,
    总路径数量 = 当前节点为起点的路径数量+当前节点的左孩子为起点的路径数量+当前节点的右孩子为起点的路径数量
    从而形成递归。而求解当前节点为起点的路径数量的方法也是通过递归完成的。
void pathSumCore(TreeNode* node, int& count, int targetSum) {
    if (targetSum == node->val)
        count++;
    if (node->left)
        pathSumCore(node->left, count, targetSum - node->val);
    if (node->right)
        pathSumCore(node->right, count, targetSum - node->val);
}
int pathSum(TreeNode* root, int sum) {
    if (!root)
        return 0;
    int count = 0;
    pathSumCore(root, count, sum);
    int left = pathSum(root->left, sum);
    int right = pathSum(root->right, sum);
    return count + left + right;
}

Leetecode 235

235. Lowest Common Ancestor of a Binary Search Tree

Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

  • 思路:
    在一个二叉搜索树中寻找两个节点的最低公共祖先。可通过递归实现,根据题目说明,可以得知当某节点值位于两个指定节点值之间时,那么该接待你即为公共祖先。所以只需要从root节点寻找,当root值大于两个指定节点值的最大值时,再从root->left进行寻找;反之从root->right进行寻找。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (!root)
        return nullptr;
    if (root->val > max(p->val, q->val))
        return lowestCommonAncestor(root->left, p, q);
    if (root->val < min(p->val, q->val))
        return lowestCommonAncestor(root->right, p, q);
    return root;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值