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

Leetcode刷题总结

二叉树刷题心得、总结


文章目录

  • Leetcode刷题总结
  • 前言
  • 一、二叉树刷题思路
  • 二、美团面试题
    • 2.1 第十套卷面试题
    • 2.2 第九套卷面试题
  • 三、华为研发工程师编程题
  • 四、华为2016研发工程师编程题


前言

二叉树有两种主要的形式:满二叉树和完全二叉树,满二叉树上只有度为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;
    }

}

你可能感兴趣的:(leetcode,算法,数据结构)