代码随想录算法训练营第十五天|Day15二叉树

找树左下角的值

题目链接/文章讲解/视频讲解: https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html

思路

咋眼一看,这道题目用递归的话就就一直向左遍历,最后一个就是答案呗?

没有这么简单,一直向左遍历到最后一个,它未必是最后一行啊。

我们来分析一下题目:在树的最后一行 找到最左边的值

首先要是最后一行,然后是最左边的值。

如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。

所以要找深度最大的叶子节点。

那么如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。

递归三部曲:

确定递归函数的参数和返回值

参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。 这里就不需要返回值了,所以递归函数的返回类型为void。

本题还需要类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。

objectivec 复制代码
int maxDepth = -1; 
int bottomLeftValue; 
void dfs(struct TreeNode* node, int depth) {
    if (node == NULL) return; 
    if (depth > maxDepth) {
        maxDepth = depth; 
        bottomLeftValue = node->val;
    }

    dfs(node->left, depth + 1); 
    dfs(node->right, depth + 1); 
}
int findBottomLeftValue(struct TreeNode* root) {
    dfs(root, 0); 
    return bottomLeftValue; 
}

学习反思

刚开始没想到一直向左遍历到最后一个,它未必是最后一行。

路径总和

题目链接/文章讲解/视频讲解:https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html

思路

1.递归

objectivec 复制代码
bool hasPathSum(struct TreeNode* root, int targetSum){
    if(!root)
        return false;
    if(!root->right && !root->left && targetSum == root->val)
        return true;
    return hasPathSum(root->right, targetSum - root->val) || hasPathSum(root->left, targetSum - root->val);
}

2.迭代

objectivec 复制代码
struct Pair {
    struct TreeNode* node;
    int sum;
};
bool hasPathSum(struct TreeNode* root, int targetSum){
    struct Pair stack[1000];
    int stackTop = 0;
    if(root) {
        struct Pair newPair = {root, root->val};
        stack[stackTop++] = newPair;
    }
    while(stackTop) {
        struct Pair topPair = stack[--stackTop];
        if(!topPair.node->left && !topPair.node->right && topPair.sum == targetSum)
            return true;
        if(topPair.node->left) {
            struct Pair newPair = {topPair.node->left, topPair.sum + topPair.node->left->val};
            stack[stackTop++] = newPair;
        }
        if(topPair.node->right) {
            struct Pair newPair = {topPair.node->right, topPair.sum + topPair.node->right->val};
            stack[stackTop++] = newPair;
        }
    }
    return false;
}

学习反思

对二叉树有更多的理解。

从中序与后序遍历序列构造二叉树

题目链接/文章讲解/视频讲解:https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html

思路

首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。

说到一层一层切割,就应该想到了递归。

来看一下一共分几步:

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

objectivec 复制代码
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    if(!preorderSize)
        return NULL;
    int rootValue = preorder[0];
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val = rootValue;
    root->left = NULL;
    root->right = NULL;
    if(preorderSize == 1)
        return root;
    int index;
    for(index = 0; index < inorderSize; index++) {
        if(inorder[index] == rootValue)
            break;
    }
    int leftNum = index;
    int rightNum = inorderSize - index - 1;

    int* leftInorder = inorder;
    int* rightInorder = inorder + leftNum + 1;
    int* leftPreorder = preorder+1;
    int* rightPreorder = preorder + 1 + leftNum;
    root->left = buildTree(leftPreorder, leftNum, leftInorder, leftNum);
    root->right = buildTree(rightPreorder, rightNum, rightInorder, rightNum);
    return root;
}
objectivec 复制代码
int linearSearch(int* arr, int arrSize, int key) {
    int i;
    for(i = 0; i < arrSize; i++) {
        if(arr[i] == key)
            return i;
    }
    return -1;
}
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
    if(!inorderSize)
        return NULL;
    struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    node->val = postorder[postorderSize - 1];
    int index = linearSearch(inorder, inorderSize, postorder[postorderSize - 1]);
    int rightSize = inorderSize - index - 1;
    node->left = buildTree(inorder, index, postorder, index);
    node->right = buildTree(inorder + index + 1, rightSize, postorder + index, rightSize);
    return node;
}

学习反思

对二叉树有更多的理解。

总结

今天的题目相对来说还是比较基础,加油!!!

相关推荐
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
搬砖的小码农_Sky6 小时前
C语言:数组
c语言·数据结构
Swift社区7 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
Kent_J_Truman7 小时前
greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用
算法
先鱼鲨生8 小时前
数据结构——栈、队列
数据结构
一念之坤8 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
IT 青年8 小时前
数据结构 (1)基本概念和术语
数据结构·算法
熬夜学编程的小王8 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
Dong雨8 小时前
力扣hot100-->栈/单调栈
算法·leetcode·职场和发展
SoraLuna8 小时前
「Mac玩转仓颉内测版24」基础篇4 - 浮点类型详解
开发语言·算法·macos·cangjie