Leetcode刷题总结-3.二叉树篇

2023-11-06

Leetcode刷题总结

二叉树刷题心得、总结



前言

二叉树有两种主要的形式:满二叉树和完全二叉树,满二叉树上只有度为0和2的节点,完全二叉树的定义是在除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置(通俗点说就是没填满的都在最后一层,而且是从左向右,没填满的都是在右边); 当然还有几种比较特殊的二叉树:二叉搜素树:二叉搜索树是一个有序树,左子树的节点的值均小于根节点的值,右子树的节点的值均大于根节点的值,同时左右子树也是搜索树,满足左小右大的性质、平衡二叉搜索树(AVL)是在为二叉搜素树的基础上,左右两个子树的高度差的绝对值不超过1,而且左右子树都是平衡二叉树。


一、二叉树刷题思路

Notes:首先来说一说递归三部曲,这是卡尔总结的,我只是学习到了做个记录,下面来看:

1)确定递归函数的参数和返回值;
2)确定终止条件;
3)确定单层逻辑;

  1. 力扣 144、94、145 题 二叉树的前、中、后序遍历, https://leetcode.cn/problems/binary-tree-preorder-traversal/、 https://leetcode.cn/problems/binary-tree-inorder-traversal/、https://leetcode.cn/problems/binary-tree-postorder-traversal/;
    思路:这三道题都是比较简单的题,二叉树的前、中、后序遍历我们按照递归三部曲来看一看;首先递归函数的给定参数一定是根节点root和需要的结果存储的数组,返回值是结果存储的数组;如果当前遍历的节点为空时就终止;单层的逻辑分别为前、中、后序遍历顺序,前序遍历就是数组先存储当前节点的值、遍历左子树、遍历右子树;中序遍历就是数组先遍历左子树、再存储当前节点的值、遍历右子树;后序遍历就是数组先遍历左子树、遍历右子树、最后存储当前节点的值。
  2. 力扣 102 题 二叉树的层序遍历, https://leetcode.cn/problems/binary-tree-level-order-traversal/;
    思路:题目描述中给你二叉树的根节点 root ,让你返回其节点值的层序遍历;层序遍历需要借用队列去实现,我这里记录自己使用非递归方法的层序遍历思路,如果给的不是空树,就先把根节点进队,进队后记录此时的size大小,用该size去pop队列中的节点,把节点值存储到数组中,pop节点的同时把左右子树的节点入队列;每次size出队列完成后,就把该数组存到一个新数组中,同时记录此时队列的大小(该大小就是这一层的节点的个数)队列变空了就说明遍历完了二叉树,最后返回新数组即可。
  3. 力扣 226 题 翻转二叉树, https://leetcode.cn/problems/invert-binary-tree/;
    思路:题目描述中给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点;这道题的思路也是十分巧妙的,使用递归去翻转每一层的节点;递归的参数为当前的节点,返回的是根节点、当前节点为空的时候就终止递归、单层的递归逻辑就是先反转当前节点的左右节点,然后递归去反转当前节点的左右节点的孩子节点。
  4. 力扣 101 题 对称二叉树,https://leetcode.cn/problems/symmetric-tree/submissions/;
    思路:题目描述中给你一个二叉树的根节点 root , 检查它是否轴对称;这道题的思路就是用迭代法去遍历这棵二叉树,首先是树为空就天然对称返回true就可以了;如果树不为空就把它的左右孩子节点入队列,在循环中检查左右孩子节点的值是否相同,如果相同就放入左孩子的左节点、右孩子的右节点、左孩子的右节点、右孩子的左节点,这样入队列的目的是每次出队列的两个节点都是我们要检验值是否相同的节点(也就是对称的节点),如果两个对称节点都为空也是对称的就继续往下走,需要加一个判断处理这种情况。
  5. 力扣 104、111 题 二叉树的最大深度、二叉树的最小深度,https://leetcode.cn/problems/maximum-depth-of-binary-tree/、https://leetcode.cn/problems/minimum-depth-of-binary-tree/submissions/;
    思路:二叉树的最大深度、最小深度本质上都是二叉树的层序遍历,只是最大深度的在每一层遍历的时候都加1而且队列不为空就一直层序遍历二叉树,而最小深度的在层序遍历的时候都加1但是只要当前节点为叶子结点(左右孩子都为空,就返回深度,结束遍历),这就是二者的差别;都是只需在层序遍历的代码上加上记录深度,最小深度多加一个判断条件。
  6. 力扣 222 题 完全二叉树的节点个数,https://leetcode.cn/problems/maximum-depth-of-binary-tree/、https://leetcode.cn/problems/minimum-depth-of-binary-tree/submissions/;
    思路:题目描述中给你一棵完全二叉树的根节点 root ,让你求该树的节点个数;这道题的思路也是比较简单的,因为求该树的节点个数就是用层序遍历的代码,只需要在每次往队列中加节点的时候用一个变量每次加1 ,最后返回这个变量就可以啦。
  7. 力扣 110 题 平衡二叉树,https://leetcode.cn/problems/maximum-depth-of-binary-tree/、https://leetcode.cn/problems/minimum-depth-of-binary-tree/submissions/;
    思路:题目描述中给你一个二叉树,让你判断它是否是高度平衡的二叉树;这道题目求的是高度,注意高度和深度不是同一个东西(高度是从该节点到叶子节点的最长简单路径边的条数,深度是从该节点到根节点的最长简单路径边的条数);既然是求高度就只能用后序遍历了,用递归去做;来看递归三部曲:
    1)递归函数给定的参数的当前节点,返回值是当前节点作为根节点的子树的高度;
    2)终止条件就是当前节点的左右子树高度差超过1;
    3)单层的逻辑就是先求左子树的高度,再求右子树的高度,看两者高度差是否超过1,超过1返回-1;没超过就计算当前树的高度。
  8. 力扣 257 题 二叉树的所有路径,https://leetcode.cn/problems/binary-tree-paths/;
    思路:题目描述中给你一个二叉树的根节点 root ,按任意顺序 ,返回所有从根节点到叶子节点的路径
    (叶子节点 是指没有子节点的节点);既然求的是叶子节点到根节点的路径,所以必须用后序遍历(这样回溯返回的才是从叶子结点返回的,直到根节点),正常来说递归实现后序遍历应该先递归左右子树,但是本题如果先递归左右子树,后把值放入path中会使最后的叶子结点没有放入路径里,所以应该先把值放入path里,再递归左右子树;递归的终止条件是当前节点为叶子结点,那么我们就需要收获结果了,把path里的数字变成字符,同时在后面拼接上题目要求的字符串,拼接完成一个path后把它放入result中,如此往复直到所有结果放入result中。
  9. 力扣 404 题 左叶子之和,https://leetcode.cn/problems/sum-of-left-leaves/;
    思路:题目描述中给定二叉树的根节点 root ,让你返回所有左叶子之和;这道题目仍然可以用递归来做,既然是要求所有左叶子之和,那么就需要找到所有的左叶子,但是本题有一个特殊的地方在于你怎么知道这个叶子结点是不是父节点的左子树呢?所以本题的递归不能遍历到叶子结点,只能遍历到叶子结点的父节点,这样才能判断这个叶子结点是不是父节点的左子树;什么时候去收获结果呢,那就是遍历到左子树的时候,判断该节点的左子树不为空,且该节点的左节点为叶子结点,就去收获结果,遍历完左子树就遍历右子树,两者的结果加起来得到最终的结果。
  10. 力扣 69 题 x 的平方根 ,https://leetcode.cn/problems/sqrtx/;
    思路:题目描述中给你一个非负整数 x ,计算并返回 x 的 算术平方根 ,由于返回类型是整数,结果只保留 整数部分 ,小数部分将被舍去 (注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 );这道题的思路就是牛顿迭代法,使用f(x)的一阶泰勒展开式去近似f(x),然后去计算x,得到x的计算公式为x=0.5*(x+a/x);得到计算公式后去计算每次迭代求出的值和上次的差值是否很小,如果差值很小就说明我们得到结果了,对它取整返回即可。
  11. 力扣 513 题 找树左下角的值 ,https://leetcode.cn/problems/find-bottom-left-tree-value/;
    思路:题目描述中给定一个二叉树的 根节点 root,让你找出该二叉树的 最底层最左边节点的值(假设二叉树中至少有一个节点);这道题用层序遍历的思路就可以解决,但是需要加上一个判断在每层进行遍历的时候,都把每层最左边的节点的值赋值给result,这样每层最左边的值一直覆盖result,最后的值一定是最后一层的最左边节点的值,也就是我们要找的答案。
  12. 力扣 112 题 路径总和,https://leetcode.cn/problems/path-sum/;
    思路:题目描述中给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和 targetSum (如果存在,返回 true ;否则,返回 false );这道题和二叉树的所有路径类似,而且不需要对路径的节点的值做转变,转变为字符串,只需要把每个路径的节点的值相加,放入result数组中,再遍历这个数组看是否有与target相同的值,没有就返回false,有就返回true。
  13. 力扣 106 题 从中序与后序遍历序列构造二叉树 ,https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/;
    思路:题目描述中给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗二叉树;这道题有点难度,需要递归的切分中序遍历和后序遍历(必须先切分中序遍历,再切分后序遍历)去构建二叉树,实现的过程就是首先找到根节点,其实找到它在中序遍历中的下标索引,其次就开始切分中序遍历、后序遍历,得到左子树的中序遍历、后序遍历和右子树的中序遍历、后序遍历;最后递归的切分左子树的中序遍历、后序遍历和右子树的中序遍历、后序遍历,构建出了一颗二叉树。
  14. 力扣 654 题 最大二叉树 ,https://leetcode.cn/problems/maximum-binary-tree/;
    思路:题目描述中给定一个不重复的整数数组 nums ,最大二叉树可以用下面的算法从 nums递归地构建:
    创建一个根节点,其值为 nums 中的最大值;递归地在最大值 左边 的 子数组前缀上构建左子树;递归地在最大值右边的子数组后缀上构建右子树;这道题的思路很明显是使用递归,首先递归的终止条件是数组大小为1的时候,就返回该节点;因为要递归的构建左右子树,所以首先需要遍历整个数组找到最大值以及下标(定义变量的时候最大值为第一个数,下标为0),定义一个节点(节点的值为该最大值),然后因为我们递归终止条件是为一个节点,所以构建左右子树的过程中需要判断左右子树是否为空,如果最大值的下标大于0说明左边子树不为空,那就构建左子树;如果最大值的下标小于数组的大小,说明右子树不为空,那就构建右子树,最后返回根节点即可。
  15. 力扣 700 题 二叉搜索树中的搜索 ,https://leetcode.cn/problems/search-in-a-binary-search-tree/;
    思路:题目描述中给定二叉搜索树(BST)的根节点 root 和一个整数值 val,你需要在 BST 中找到节点值等于 val 的节点。返回以该节点为根的子树。如果节点不存在,则返回null ;二叉搜索树是左子树的值都小于根节点、右子树的值都大于根节点的树,二叉树的搜索这道题目的思路就是用递归,用递归三部曲来分析:递归的传递参数就是当前的节点和要寻找的值,返回参数是等于要找的等于特定的值的节点(或者返回空节点);当前节点为空节点是终止条件,说明已经到叶子结点了,需要向上返回了或者已经找到要找的节点;单层的逻辑是递归在节点的左子树和右子树寻找等于特定的值的节点,最后返回结果即可。
  16. 力扣 98 题 验证二叉搜索树 ,https://leetcode.cn/problems/validate-binary-search-tree/;
    思路:题目描述中给你一个二叉树的根节点 root ,让你判断其是否是一个有效的二叉搜索树;这道题很有意思,如果给你一个数组让你判断数组是否单调递增肯定都会,但是给你一个二叉树让你判断其是否是一个有效的二叉搜索树确蒙圈了,其实我还是对二叉树的遍历方式不是特别懂,这道题用中序遍历就可以得到一个单调递增的数组了,所以这道题有两个思路:一是把中序遍历得到的结果存到一个数组中,然后判断数组是否单调递增即可;二是双指针, 用一个节点记录上一个遍历过的节点,如果上一个节点的值大于等于当前节点的值,这棵树就不是二叉搜索树返回false,否则就更新pre指针,继续进行遍历,最后左右子树得到的结果综合,最终的返回结果。
  17. 力扣 530 题 二叉搜索树的最小绝对差 ,https://leetcode.cn/problems/minimum-absolute-difference-in-bst/;
    思路:题目描述中给你一个二叉搜索树的根节点 root ,返回树中任意两不同节点值之间的最小差值(差值是一个正数,其数值等于两值之差的绝对值);这道题如果验证二叉搜索树会了,这道题就很简单,继续用中序遍历得到数组,遍历数组,得到两个相邻的值的差,取最小的即可。
  18. 力扣 501 题 二叉搜索树中的众数 ,https://leetcode.cn/problems/find-mode-in-binary-search-tree/;
    思路:题目描述中给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有众数(如果树中有不止一个众数,可以按任意顺序返回);怎么找众数呢?这道题仍然是用中序遍历,但是难点在于怎么把众数找出来,也就是,在处理的逻辑中,我们仍然用双指针;两个指针指向的节点的值一样,那就计数值加1,否则计数值就重新赋为1,第一次进循环的时候直接计数值赋为1即可;为了找到众数,需要一个计数值和一个最大值(用来记录计数值中最大的值的变量),每次把计数值等于最大值的放入存放结果的数组中,如果计数值大于最大值,那就更新最大值,同时把结果集清空,把当前的节点的值再重新放入结果集中;核心就是滚动更新pre指针、结果集、最大值,最终得到结果。
  19. 力扣 617 题 合并二叉树 ,https://leetcode.cn/problems/merge-two-binary-trees/;
    思路:题目描述中给你两棵二叉树,让你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠,你需要将这两棵树合并成一棵新二叉树(合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点,返回合并后的二叉树);这道题目是比较简单的,来看递归三部曲:递归的参数是当前的两颗树的节点,返回值是合并后树的根节点;当一棵树对应的位置节点为空的时候就可以终止递归,返回另一棵树的该节点即可;单层的逻辑就是根节点的值等于两个树对应节点值相加,然后在左子树上合并,在右子树上合并,最后返回根节点。
  20. 力扣 700题 二叉搜索树中的搜索, https://leetcode.cn/problems/search-in-a-binary-search-tree/;
    思路:题目描述中给定二叉搜索树(BST)的根节点 root 和一个整数值 val,你需要在 BST 中找到节点值等于 val 的节点(返回以该节点为根的子树。 如果节点不存在,则返回 null );在二叉搜索树中找节点值,用后序遍历来遍历二叉树,来看递归三部曲的步骤:递归的参数是当前的节点和要寻找的节点值,返回值是找到的节点;当前节点为空或者当前的节点等于要寻找的节点值,就返回该节点;单层递归的逻辑就是判断当前节点值和要寻找的节点值的大小关系,然后向左子树或右子树继续寻找。
  21. 力扣 98题 验证二叉搜索树,https://leetcode.cn/problems/validate-binary-search-tree/;
    思路:题目描述中给你一个二叉树的根节点 root ,让你判断其是否是一个有效的二叉搜索树;判断是否为
    一个有效的二叉搜索树(有一个很容易犯错的地方,我自己就犯错了,就是递归的去遍历树,判断当前节点的左孩子小于节点值,右孩子大于节点值,这样的问题在于不能验证根节点的左子树值是否均小于根节点,也不能验证根节点的右子树值是否均大于根节点,所以就会出错,判断错误),正确的做法是用两个节点的值循环比较,其中cur节点就是依次后续遍历的节点,pre节点是上一个cur节点,这样遍历只要pre节点的值一直小于cur节点即可。
  22. 力扣 530题 二叉搜索树的最小绝对差,https://leetcode.cn/problems/minimum-absolute-difference-in-bst/;
    思路:题目描述中给你一个二叉搜索树的根节点 root ,让你返回树中任意两不同节点值之间的最小差值 (差值是一个正数,其数值等于两值之差的绝对值);这道题思路很简单,把二叉搜索树的后序遍历结果放到数组中,循环找相邻两个数的最小差值即可。
  23. 力扣 235 题 二叉搜索树的最近公共祖先,https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/;
    思路:题目描述中给定一个二叉搜索树, 让你找到该树中两个指定节点的最近公共祖先;递归三部曲:递归参数是当前的节点和要寻找的两个节点值,返回值是两个节点的最近公共祖先;如果遍历到空节点或者找到了其中一个节点值就返回;单层的逻辑是向左子树寻找、向右子树寻找,如果两个子树返回值都不为空,那就返回左右子树的最近公共祖先。
  24. 力扣 701 题 二叉搜索树中的插入操作,https://leetcode.cn/problems/insert-into-a-binary-search-tree/;
    思路:题目描述中给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树,返回插入后二叉搜索树的根节点(输入数据保证 ,新值和原始二叉搜索树中的任意节点值都不同
    );递归三部曲:递归的参数为当前的节点和要插入树中的值 value,返回值为新的节点;当遍历到空节点的时候,证明已经找到合适的位置了,定义节点,把节点返回给上一层即可;单层递归的逻辑是遍历左子树、遍历右子树,最后返回根节点即可。
  25. 力扣 450 题 删除二叉搜索树中的节点,https://leetcode.cn/problems/delete-node-in-a-bst/;
    思路:题目描述中给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变(返回二叉搜索树(有可能被更新)的根节点的引用);这道题目要处理几种情况:一是要删除节点左子树、右子树都为空,二是左子树为空、右子树不为空,三是左子树不为空、右子树为空,四是左子树、右子树都为不为空;第一种情况直接返回空节点,第二种情况返回右孩子的节点,第三种情况返回左孩子的节点,第四种情况麻烦一点,需要先在该节点的左孩子上一直找右孩子,直到右孩子的孩子为空,此时把该节点的右孩子的子树放到这里来,返回左孩子即可。,这是对找到节点的操作,相当于终止条件,下面就是单层逻辑的执行,向左子树寻找、右子树寻找,最后返回根节点。
  26. 力扣 669 题 修剪二叉搜索树,https://leetcode.cn/problems/trim-a-binary-search-tree/;
    思路:题目描述中给你二叉搜索树的根节点 root ,同时给定最小边界low和最大边界 high,让你通过修剪二叉搜索树,使得所有节点的值在[low, high]中(修剪树不应该改变保留在树中的元素的相对结构);递归三部曲:递归的参数是当前的节点、节点的值的上界和下界,返回值是根节点;当遍历到空节点的时候就终止;单层递归的逻辑就是当前节点值小于下界,那就去当前节点的右子树寻找合适的节点并返回节点,当前节点值大于下上界,那就去当前节点的左子树寻找合适的节点并返回节点;最终返回根节点即可。
  27. 力扣 108 题 将有序数组转换为二叉搜索树,https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/;
    思路:题目描述中给你一个整数数组 nums ,其中元素已经按升序排列,让你将其转换为高度平衡的二叉搜索树;递归三部曲:递归的参数是数组和数组的左、右下标,返回值是根节点;当左下标大于右下标(没有值了)就终止;单层的逻辑,首先是处理中间节点(也就是根节点第)的逻辑,左、右下标相加除以2得到中间值的下标,然后定义一个节点,把节点值赋为刚才的中间值,然后左下标到中间下标之前的递归去分割,中间下标到右下标的递归去分割,最后返回根节点。
  28. 力扣 538 题 把二叉搜索树转换为累加树,https://leetcode.cn/problems/convert-bst-to-greater-tree/;
    思路:题目描述中给出二叉 搜索树的根节点,该树的节点值各不相同,让你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和;因为是从右子树累加到根节点,再从根节点累加到左子树这样执行的,来看递归三部曲:递归参数是当前遍历的节点,返回值根节点;当遍历到根节点的时候就终止;递归遍历右子树、然后当前节点的值等于前节点的值加上它的右子树的值(也就是上一层递归节点的值)、遍历左子树,最终返回根节点即可。Notes:这里记录上一层遍历的节点的值用一个变量定义在函数之前,然后在加上节点的值语句后,把当前节点的值赋值给该变量即可。

二、美团面试题

2.1 第十套卷面试题

1)输入第一行仅包含三个正整数n,x,y,分别表示参赛的人数和晋级淘汰人数区间(1<=n<=50000,1<=x,y<=n);输入第二行包含n个整数,中间用空格隔开,表示从1号选手到n号选手的成绩(1<=|a_i|<=1000)。
晋级和淘汰的人数均在[x,y]之间,显然这个m有可能是不存在的,也有可能存在多个m,如果不存在,请你输出-1,如果存在多个,请你输出符合条件的最低的分数线。
思路:这道题我没做出来,看了网上别人的解答才明白,思路就是既然晋级和淘汰的人数均要在[x,y]之间,首先来判断n是否满足条件,也就是n>=2x,n<=2y,因为n一旦不符合这个条件,那么晋级和淘汰的人数就不符合条件了,直接输出-1即可;满足条件的情况下题目说了要分数线要最低,那就是晋级的人数在满足条件的情况下尽可能多,因此需要淘汰的人数应该在y和n-x中取最小值,这样可以限制晋级人数不会超过y,然后输出淘汰人中最高的分数即可。(这里需要对分数进行排序,题目说了晋级的人数都大于m,所以要输出的是淘汰人中最高的分数,在数组中找到对应的下标,索引找到后输出它即可)。

2)我们称一个长度为n的序列为正则序列,当且仅当该序列是一个由1~n组成的排列,即该序列由n个正整数组成,取值在[1,n]范围,且不存在重复的数,同时正则序列不要求排序;
有一天小团得到了一个长度为n的任意序列s,他需要在有限次操作内,将这个序列变成一个正则序列,每次操作他可以任选序列中的一个数字,并将该数字加一或者减一。请问他最少用多少次操作可以把这个序列变成正则序列?
输入第一行仅包含一个正整数n,表示任意序列的长度。(1<=n<=20000)
输入第二行包含n个整数,表示给出的序列,每个数的绝对值都小于10000。
输出仅包含一个整数,表示最少的操作数量。
思路:首先对给定的n个整数排序,刚开始我还被题目说的正则序列不要求排序迷惑了,我以为这个数组不需要排序,但是你不排序的话怎么知道你对每个数操作在1-n范围内后,没有重复的数呢,所以只能先排序,把每个数操作到1-n的大小内,这样的话操作次数才是最少的;后面就很简单了,把每个数的操作次数加起来就得到结果了。

2.2 第九套卷面试题

1)小团的蛋糕铺长期霸占着美团APP中“蛋糕奶茶”栏目的首位,因此总会吸引各路食客前来探店。
小团一天最多可以烤n个蛋糕,每个蛋糕有一个正整数的重量。早上,糕点铺已经做好了m个蛋糕。
现在,有一个顾客要来买两个蛋糕,他希望买这一天糕点铺烤好的最重的和最轻的蛋糕,并且希望这两个蛋糕的重量恰好为a和b。剩余的n-m个蛋糕可以现烤,请问小团能否满足他的要求?
输入描述:输入包含多组数据,每组数据两行。每组数据的第一行包含4个整数,n,m,a,b,空格隔开。这里不保证a和b的大小关系。接下来一行m个数,空格隔开,代表烤好的蛋糕重量。
输出描述:对于每一组数据,如果可以办到顾客的要求,输出YES,否则输出NO。
思路:要买的蛋糕必须是当天最重的和最轻的,因此就需要分几种情况讨论:1)已经做好的均小于a或者均大于b;2)已经做好的都在a-b之间;3)已经做好的包含了要的a或b,或者a和b都有;
根据情况我们把做好的蛋糕计数为小于a、等于a、大于a小于b、等于b、大于b;分别按照每种情况讨论即可。比如都在a-b之间,就需要判断还没做的蛋糕数目大于等于2那就可以满足顾客要求,小于2就不能满足。
2)小团是综艺节目的策划,他为某个游戏环节设计了一种晋级规则,已知在这个游戏环节中每个人最后都会得到一个分数score_i,显而易见的是,游戏很有可能出现同分的情况,小团计划该环节晋级人数为x人,则将所有人的分数从高到低排序,所有分数大于等于第x个人的分数且得分不为0的人都可以晋级。请你求出本环节的实际晋级人数。显然这个数字可能是0,如果所有人的得分都是0,则没有人满足晋级条件。
输入描述:输入第一行包含两个正整数n和x,分别表示参加本环节的人数,和小团指定的x。
输入第二行包含n个整数,每个整数表示一位选手的得分。
输出描述:输出仅包含一个整数,表示实际晋级人数。
思路:首先从高到低排序分数,然后遍历这个分数,如果大于等于x而且不为0,那么晋级人数加1,最后输出晋级人数。
3)小美请小团吃回转寿司。转盘上有N盘寿司围成一圈,第1盘与第2盘相邻,第2盘与第3盘相邻,…,第N-1盘与第N盘相邻,第N盘与第1盘相邻。小团认为第i盘寿司的美味值为A[i](可能是负值,如果小团讨厌这盘寿司)。现在,小团要在转盘上选出连续的若干盘寿司,使得这些寿司的美味值之和最大(允许不选任何寿司,此时美味值总和为0)。
输入描述:第一行输入一个整数T(1<=T<=10),表示数据组数。
每组数据占两行,第一行输入一个整数N(1<=N<=10^5);
第二行输入N个由空格隔开的整数,表示A[1]到A[N](-104<=A[i]<=104)。
输出描述:每组数据输出占一行,输出一个整数,表示连续若干盘寿司的美味值之和的最大值。
思路:这道题的思路也是比较巧妙的,首先如果第一个数为负数,那么其实连成环和不连求出来的一样,,那么我们按照正常求连续子数组的最大和即可;但是如果第一个数不为负,而且连续子数组的最大和包含首尾元素,那么就需要去计算所有数加起来的和,再去计算连续子数组的最小和,两者相减就得到了结果,因为最小子数组和最大子数组一定是互补的,所以去掉最小的和之后就是最大的啦。

三、华为研发工程师编程题

1)汽水瓶,某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。
小张手上有n个空汽水瓶,她想知道自己最多可以喝到多少瓶汽水;
输入描述:输入文件最多包含 10 组测试数据,每个数据占一行,仅包含一个正整数 n( 1<=n<=100 ),表示小张手上的空汽水瓶数。n=0 表示输入结束,你的程序不应当处理这一行;
输出描述:对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0;
思路:这道题目很简单,可以借空汽水瓶的意思就是两个瓶子就可以喝一瓶汽水,因为借一个空瓶子获得一瓶汽水后喝完再还给他即可,所以输入整除2输出即可
2)明明生成了N个1到500之间的随机整数,请你删去其中重复的数字,即相同的数字只保留一个,把其余相同的数去掉,然后再把这些数从小到大排序,按照排好的顺序输出;
输入描述:第一行先输入随机整数的个数 N,接下来的 N 行每行输入一个整数,代表明明生成的随机数;
输出描述:输出多行,表示输入数据处理后的结果;
思路:把输入的数字放入集合中(set),然后用auto类型(auto x : s)把结果输出即可
3)十六进制转换十进制,写出一个程序,接受一个十六进制的数,输出该数值的十进制表示;
输入描述:输入一个十六进制的数值字符串;
输出描述:输出该数值的十进制字符串。不同组的测试用例用\n隔开;
思路:从低位开始把字符与‘0’或者'A'作差后('A'作差要加10),得到的数乘以16的第几位减一的次方,然后累加之后输出即可。

四、华为2016研发工程师编程题

1)有一个数组 a[N] 顺序存放 0 ~ N-1 ,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置,以 8 个数 (N=7) 为例 :{ 0,1,2,3,4,5,6,7 },0 -> 1 -> 2 (删除) -> 3 -> 4 -> 5 (删除) -> 6 -> 7 -> 0 (删除),如此循环直到最后一个数被删除;
输入描述:每组数据为一行一个整数n(小于等于1000),为数组成员数
输出描述:一行输出最后一个被删掉的数的原始下标位置;
思路:这道题目是经典的约瑟夫环的问题,每隔两个元素循环删除一个元素,思路是通过对数组的大小取余实现循环,删除的元素要设置标志,表示已经删除了,再遇到的话直接跳过继续,当操作的次数没有到达数组的大小时,继续操作(同时每次操作记录删除的元素下标,这么做的目的是删除完元素后直接输出这个下标就是要求的结果)。

int main() {
    int n;
    while(cin >> n) {
        int countSize = n;
        int count = 0;
        int i = 0;
        int lastIndex = 0;
        vector<int> nums(n, 0);
        for(int i = 0; i <n; i++) {
            nums[i] = i;
        }

        while(countSize != 0) {
            if(nums[i] != DELFLAG) {
                if(count++ == STEP) {
                    lastIndex = i;
                    nums[i] = DELFLAG;
                    count = 0;
                    countSize--;
                }
            }
            i = (i + 1) % n;
        }
        cout << lastIndex << endl;
    }
}

2)输入一个字符串,求出该字符串包含的字符集合,按照字母输入的顺序输出;
输入描述:每组数据输入一个字符串,字符串最大长度为100,且只包含字母,不可能为空串,区分大小写;
输出描述:每组数据一行,按字符串原有的字符顺序,输出字符集合,即重复出现并靠后的字母不输出;
思路:这道题的收获在于怎么读取多行字符,要用getline(cin,str)读取,用之前读取整数的方式不可取,会把所有行的字符串读到一个字符串里,然后通过集合进行去重,要加入集合的元素就是不重复的元素,因此就把它添加到要输出的字符号串中,最后输出字符串即可。

int main() {

    string input;
    while(getline(cin, input)) {
        if(input.empty()) break;

        string result;
        unordered_set<char> uniqueChars;

        for(auto ch : input) {
            if(uniqueChars.find(ch) == uniqueChars.end()) {
                uniqueChars.insert(ch);
                result += ch;
            }
        }

        cout << result << endl;
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Leetcode刷题总结-3.二叉树篇 的相关文章

随机推荐

  • RunBlocking CoroutineScope SupervisorScope Launch Async CoroutineStart协程启动模式 Job对象和生命周期

    协程的作用域构建器 RunBlocking runBlocking是常规函数 会把当前主线程包装成一个主协程 其会阻塞当前线程 只有当等待其主协程体以及里面的所有子协程执行结束以后 才会让当前线程执行 CoroutineScope coro
  • QT foreach

    如果只想按顺序迭代容器中的所有项 可以使用Qt的foreach关键字 该关键字是对C 语言的Qt特定添加 并使用预处理器实现 与任何其他C 循环构造一样 您可以在foreach循环的主体周围使用大括号 并且可以使用Break来离开循环 其语
  • 华为OD机试 - 数组连续和(Java)

    题目描述 给定一个含有N个正整数的数组 求出有多少个连续区间 包括单个正整数 它们的和大于等于x 输入描述 第一行两个整数N x 0 lt N lt 100000 0 lt x lt 10000000 第二行有N个正整数 每个正整数小于等于
  • 锐捷交换机密码破解

    资料来源 https search ruijie com cn 8447 rqs preview html ie utf 8 wd eHAiOjE1NDU4NzUxNDcsIm5iZiI6MTU0NTYxNTk0N3020180920150
  • 虚拟机-扩充硬盘

    扩充硬盘 https www cnblogs com wy20110919 p 9150914 html https cloud tencent com developer article 1563508 from 14588
  • next_permutation(a,a+n)

    早就听说了了next permutation 产生全排列的强大 一直到昨晚遇到一个对字符串产生全排列的问题才知道这个函数的强大 我们队是按照dfs去搞全排列 然后在进行字符串的匹配 结果写的很长 过程中还各种debug 于是决定今天学一下
  • 认知-想象力:想象力

    ylbtech 认知 想象力 想象力 想象力 是人在已有形象的基础上 在头脑中创造出新形象的能力 比如当你说起汽车 我马上就想像出各种各样的汽车形象来就是这个 道理 因此 想象一般是在掌握一定的知识面的基础上完成的 想象力 是在你头脑中创造
  • Spring学习笔记(一)【BeanUtils.copyProperties方法】

    Spring下的BeanUtils copyProperties方法是深拷贝还是浅拷贝 一 浅拷贝深拷贝的理解 简单地说 拷贝就是将一个类中的属性拷贝到另一个中 对于BeanUtils copyProperties来说 必须保证属性名和类型
  • 【不忘初心】Win11_21H2_22000.100_X64_四合一[纯净精简版][2.9G](2021.8.5)

    此版更新补丁未知 WIN11全新的UI界面出炉 可以说这一次Windows 11全新升级 无论是从Logo上还是UI界面设计 都有很大的变化 不过WIN11目前还不够稳定 小问题比较多 母版来自MSDN WIN11 21H2 22000 1
  • 大学概率论与数理统计知识点详细整理

    目录 概率论学习自述 概率论的一些基本概念 随机变量的分布 一维随机变量的分布 二维随机变量 抽样分布 数学期望 矩 方差 协方差 常见分布的数学期望与方差 一些重要的定理公式 参数估计 1 点估计 2 区间估计 假设检验 独立性 概率论学
  • 蒙皮流程1

    选中要调整权重的点 打开这个窗口 可以调整他的权重值 蒙皮里面的导出导入权重贴图可以在要对模型做修改的情况下 对已弄好的权重进行保留 或者直接用下面的替换几何体用新的替换旧的 给人物下巴绘制权重时 下巴骨骼与躯干骨骼连接处插入一个小骨骼 给
  • Unity ScrollView左右拖拽翻页

    ScrollView来实现左右拖拽的翻页 类似于微信 左右拖拽时候上下无法拖拽 上下拖拽的时候左右无法拖拽 并且左右拖拽的是时候 会有弹力进行对对齐 using System Collections using System Collect
  • C++这么难,为什么我们还要学习C++?

    文章目录 前言 1 为什么难学 2 C 的意义 3 什么时候该用C 4 如何学习C 5 学前勉言 前言 C 可算是一种声名在外的编程语言了 这个名声有好有坏 从好的方面讲 C 性能非常好 哪个编程语言性能好的话 总忍不住要跟 C 来单挑一下
  • Linux下WiFi驱动开发——WiFi基础知识解析(转)

    详见 https blog csdn net zqixiao 09 article details 51103615
  • SQL Server 命令行管理工具:SqlLocalDB.exe

    SqlLocalDB exe 是一个简单的工具 它使用户能够从命令行轻松管理 LocalDB 实例 它作为 LocalDB 实例 API 的简单包装实现 与在很多类似的 SQL Server 工具 例如 SQLCMD 中一样 参数作为命令行
  • flask框架实现文件下载功能

    传入文件名即可下载文件 from flask import Flask send file Response send from directory app Flask name app route download def downloa
  • Python编程题

    把数组 0 1 1 0 1 1 0 1 1 1 0 0 中所有的1排到左侧 0排到右侧 方法1 思路 1 首先进行可以保证0在左侧 1在右侧 2 新建一个空列表 3 把原列表中的值从最后1个复制给新建列表 直到第一个元素被复制完 list1
  • Qt 画图,void A::paintEvent(QPaintEvent *event){..}这函数怎么调用它?

    不用调用 需要用这个函数的时候调用A gt update 就可以得到调用这个函数的目的
  • shell中单引号、双引号、反引号的用法及区别

    单引号 这个比较暴力 不管单引号里面有什么都原样输出 无视一切变量 所见即所得 如果要用来做字符比较和输出 注意不能输出变量 也不认识通配符 命令等 even ubuntu echo a PATH aa a PATH aa 双引号 双引号感
  • Leetcode刷题总结-3.二叉树篇

    Leetcode刷题总结 二叉树刷题心得 总结 文章目录 Leetcode刷题总结 前言 一 二叉树刷题思路 二 美团面试题 2 1 第十套卷面试题 2 2 第九套卷面试题 三 华为研发工程师编程题 四 华为2016研发工程师编程题 前言