leetcode每日刷题

简介: leetcode每日刷题

🏆一、二叉搜索树的后序遍历序列


来源:leetcode、二叉搜索树的后序遍历序列


输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。


1669268432788.jpg


这道题目有点意思,如果找不到思路很难判断数组是否为一个二叉树后序遍历的结果。我们知道在后序遍历得到的序列中,最后一个数必然是根,然后前面的元素被分成两部分:左子树节点的值和右子树节点的值。而左右子树内部也遵循着后序遍历的原则。以题目给的二叉树的后序遍历为例,

1669268442021.jpg

这段序列的根为5,5的左子树节点的值为1,3,2;5的右子树节点的值为6.这其中左子树节点的值都小于根节点的值,右子树节点的值都大于右节点的值。然后左右子树内部也是一样的最后一个元素为根,左子树都比根小,右子树都比根大。这是一个递归的过程,如果都满足这样的规则,很显然这个序列是一个二叉树的后序遍历。


🖊递归求解


1、先把数组最后一个元素存下来(根),然后遍历其余数,如果遇到有值大于根,就停下来,这代表左右子树的分界线。


2、因为分界线左边的数值必定小于根,所以只要判断分界线右边的数,也就是右子树部分如果有数值小于根的值,说明不是一个二叉树的后序遍历,返回false。


3、不断划分数组区间,递归。


bool verifyPostorder(int* postorder, int postorderSize)
{
    //左子树都比根小
    //右子树都比根大
    if(postorder==NULL||postorderSize<1)
        return true;
    int root=postorder[postorderSize-1];
    int i=0;
    for(i=0;i<postorderSize-1;++i)
    {
        if(postorder[i]>root)
            break;
    }
    for(int j=i;j<postorderSize-1;++j)
    {
        if(postorder[j]<root)
            return false;
    }
    bool left=true;
    if(i>0)
        left=verifyPostorder(postorder,i);
    bool right=true;
    if(i<postorderSize-1)
        right=verifyPostorder(postorder+i,postorderSize-1-i);
    return (left&&right);
}


🏆二、二叉树中和为某一值的路径


来源:leetcode、二叉树中和为某一值的路径


给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。


叶子节点 是指没有子节点的节点。


1669268477049.jpg


困难解法:BFS广度优先,把二叉树的层序遍历拿下来放到一个数组,在这同时用一个数组记录所有叶子节点在层序遍历数组中的下标。然后通过叶子节点去找父节点,(parent=(child-1)/2)满足加和等于target的路径记录下来。(博主写过,非常麻烦,在leetcode上直接超时跑不过去)。


🖊DFS递归求解


我们从根出发,不断访问子节点,当访问到叶子节点的时候,我们不仅要计算这条路径节点的值的和还要记录这一路径的所有节点的值,这就要求我们开辟一个数组记录这条路径上所有的值,当加和满足等于target时,我们就把这条路径上的值放到二维数组里面。如果走到叶子节点不满足加和等于target呢,我们要去掉这个叶子节点,也就是指向数组最后一个元素的指针--,(这里类似于栈pop出栈顶)。判断另一个叶子节点,综合下来整体类似于前序遍历。

int**ret;
 int*retColSize;
 int retSize;
 int* path;
 int pathSize;
 const int MAX_Node=5001;
 //要返回的路径
void dfs(struct TreeNode* root,int target)
{
    if(root==NULL)
        return;
    path[pathSize++]=root->val;
    target-=root->val;
    if(root->left==NULL&&root->right==NULL&&target==0)//为叶子节点并且target==0,就是我们要找的路径时
    {
        int* tmp=(int*)calloc(pathSize,sizeof(int));
        memcpy(tmp,path,sizeof(int)*pathSize);//为什么不直接把path给到retSize呢?因为没必要,我们只需要拷贝前pathSize的数据是有效数据
        ret[retSize]=tmp;
        retColSize[retSize]=pathSize;
        retSize++;
    }
    dfs(root->left,target);
    dfs(root->right,target);
    pathSize--;//返回上一层递归时需要pathSize--
}
int** pathSum(struct TreeNode* root, int target, int* returnSize, int** returnColumnSizes)
{
    ret=(int**)calloc(MAX_Node,sizeof(int*));//要返回的二维数组
    retColSize=(int*)calloc(MAX_Node,sizeof(int));//要求返回的二维数组每组多少个元素
    path=(int*)calloc(MAX_Node,sizeof(int));
    retSize=pathSize=0;
    dfs(root,target);//深度优先递归
    *returnSize=retSize;
    *returnColumnSizes=retColSize;
    return ret;
}

这里还有几处细节和一些小tips:


1、为什么设为全局变量?(新get到的小技能)


如果我们在main函数里面设立局部变量,不仅需要传参,而且最重要的是递归参数不能传值,需要传地址,这可能要涉及到二级甚至三级指针,非常麻烦,传大量的参,还需要考虑参数的变化,甚至我们需要设一些返回值去接受,/(ㄒoㄒ)/~~全局变量的好处在这里就体现了出来。


2、为什么用中间变量拷贝再赋给二维数组?

1669268499012.jpg

这三行代码为什么不写成:


ret[retSize]=path;

这多好,为何多此一举还要用tmp呢?


①第一种写法pathSize个数据是我们需要的有效数据,其余并不需要,我们拷贝到的都是有效数据。


②第二种写法的问题会报错:1、你拷贝进了除pathSize个以外的其他无效数据,没必要;


2、你无法确定path的空间是否小于等于二维数组中的一维数组的空间,强行给的话可能会导致放不下,溢出报错。

相关文章
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
41 6
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
35 4
|
1月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
73 2
|
1月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
36 7
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
17 4
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
40 5
|
1月前
|
算法 Python
【Leetcode刷题Python】 LeetCode 2038. 如果相邻两个颜色均相同则删除当前颜色
本文介绍了LeetCode 2038题的解法,题目要求在一个由'A'和'B'组成的字符串中,按照特定规则轮流删除颜色片段,判断Alice是否能够获胜,并提供了Python的实现代码。
36 3
|
1月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
15 3
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - II. 从上到下打印二叉树 II
本文提供了一种Python实现方法,用于层次遍历二叉树并按层打印结果,每层节点按从左到右的顺序排列,每层打印到一行。
28 3
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
Leetcode题目"剑指 Offer 21. 调整数组顺序使奇数位于偶数前面"的两种Python解决方案,一种是使用双端队列调整数组顺序,另一种是使用双指针法将奇数移到数组前半部分,偶数移到后半部分。
21 4