抽奖概率算法_题库 | LeetCode算法题,内附解析,来试试吧

9dd198905141fa8e7c88f9c48ca8b693.png

序列化二叉树的一种方法是使用前序遍历。当我们遇到一个非空节点时,我们可以记录下这个节点的值。如果它是一个空节点,我们可以使用一个标记值记录,例如#.
     _9_
    /   \
   3     2
  / \   / \
 4   1  #  6
/ \ / \   / \
# # # #   # #
例如,上面的二叉树可以被序列化为字符串 "9,3,4,#,#,1,#,#,2,#,6,#,#",其中#代表一个空节点。 给定一串以逗号分隔的序列,验证它是否是正确的二叉树的前序序列化。编写一个在不重构树的条件下的可行算法。 每个以逗号分隔的字符或为一个整数或为一个表示 null 指针的'#'。 你可以认为输入格式总是有效的,例如它永远不会包含两个连续的逗号,比如 "1,,3"。
示例 1: 输入: "9,3,4,#,#,1,#,#,2,#,6,#,#" 输出: true 示例 2: 输入: "1,#" 输出: false 示例 3: 输入: "9,#,#,1" 输出: false
不需要建立解法一中的额外数组,而是边解析边判断,遇到不合题意的情况直接返回 false,而不用全部解析完再来验证是否合法,提高了运算的效率。我们用一个变量 degree 表示能容忍的 "#" 的个数,degree 初始化为 1。再用一个布尔型变量 degree_is_zero 来记录 degree 此时是否为 0 的状态,这样的设计很巧妙,可以 cover 到 "#" 开头,但后面还跟有数字的情况,比如 "#,1,2" 这种情况,当检测到 "#" 时,degree 自减 1,此时若 degree 为 0 了,degree_is_zero 赋值为 true,那么如果后面还跟有其他东西的话,在下次循环开始开始前,先判断 degree_is_zero,如果为 true 的话,直接返回 false。而当首字符为数字的话,degree 自增 1,那么此时 degree 就成了 2,表示后面可以再容忍两个 "#"。当循环退出的时候,此时判断 degree 是否为 0,因为我们要补齐 "#" 的个数,少了也是不对的。
class Solution {public:        bool isValidSerialization(string preorder) {        istringstream in(preorder);                string t = "";                int degree = 1;                bool degree_is_zero = false;;                while (getline(in, t, ',')) {                        if (degree_is_zero) return false;                        if (t == "#") {                                if (--degree == 0) degree_is_zero = true;            } else ++degree;        }                return degree == 0;    }};

e091193612da1f756ddbdf4770a22b0c.png

给定一个已排序的正整数数组 nums,和一个正整数 n 。从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。请输出满足上述要求的最少需要补充的数字个数。 示例 1: 输入: nums = [1,3], n = 6 输出: 1 解释:根据 nums 里现有的组合 [1], [3], [1,3],可以得出 1, 3, 4。现在如果我们将 2 添加到 nums 中, 组合变为: [1], [2], [3], [1,3], [2,3], [1,2,3]。其和可以表示数字 1, 2, 3, 4, 5, 6,能够覆盖 [1, 6] 区间里所有的数。所以我们最少需要添加一个数字。 示例 2: 输入: nums = [1,5,10], n = 20 输出: 2 解释: 我们需要添加 [2, 4]。 示例 3: 输入: nums = [1,2,2], n = 5 输出: 0 我们定义一个变量 miss,用来表示 [0,n] 之间最小的不能表示的值,那么初始化为 1,为啥不为 0 呢,因为 n=0 没啥意义,直接返回 0 了。那么此时我们能表示的范围是 [0, miss),表示此时我们能表示 0 到 miss-1 的数,如果此时的 num <= miss,那么我们可以把我们能表示数的范围扩大到 [0, miss+num),如果 num>miss,那么此时我们需要添加一个数,为了能最大限度的增加表示数范围,我们加上 miss 它本身,以此类推直至遍历完整个数组,我们可以得到结果。 举个例子说明: 给定 nums = [1, 2, 4, 11, 30], n = 50,我们需要让 [0, 50] 之间所有的数字都能被 nums 中的数字之和表示出来。 首先使用 1, 2, 4 可能表示出 0 到 7 之间的所有数,表示范围为 [0, 8),但我们不能表示 8,因为下一个数字 11 太大了,所以我们要在数组里加上一个 8,此时能表示的范围是 [0, 16),那么我们需要插入 16 吗,答案是不需要,因为我们数组有 1 和 4,可以组成 5,而下一个数字 11,加一起能组成 16,所以有了数组中的 11,我们此时能表示的范围扩大到 [0, 27),但我们没法表示 27,因为 30 太大了,所以此时我们给数组中加入一个 27,那么现在能表示的范围是 [0, 54),已经满足要求了,我们总共添加了两个数 8 和 27,所以返回 2 即可。
class Solution {public:        int minPatches(vector& nums, int n) {                long miss = 1, res = 0, i = 0;                while (miss <= n) {                        if (i < nums.size() && nums[i] <= miss) {                miss += nums[i++];            } else {                miss += miss;                                ++res;            }        }                return res;    }};

aad39a844b743118e7d6061e785b2df3.png

给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。 数学表达式如下: 如果存在这样的 i, j, k,  且满足 0 ≤ i 使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。 说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。 示例 1: 输入: [1,2,3,4,5] 输出: true 示例 2: 输入: [5,4,3,2,1] 输出: false "中间" 那个数是很重要的。所以就是用 m 来代替。m 之前始终有个比他小的数(l,或曾经的 l)。所以如果当前遍历到的元素大于了 m,那么就 return true。
 1 class Solution {  2     public boolean increasingTriplet(int[] nums) {  3         int numsSize=nums.length;  4         if(numsSize<3) return false;  5         int l=nums[0],m=Integer.MAX_VALUE;  6         for(int i=1;i 7             int a=nums[i];  8             if(a<=l) l=a;  9             else if(a 10             else if(a>m) return true; 11         } 12         return false; 13     } 14 }

cdbee9abf8ac5a94c6dd20f338da1d97.png

d9796f848a011dde3e8db28ee65c9c16.png

题库 | 机智的你,这些题目一定能做对吧!

题库 | 想面腾讯?先看看这3道历年面试真题吧

题库 | 腾讯春招2018编程题

cafebbd4c31736397d135127336e4cde.gif

aa9dbbc0c3181e52ab783ab92de53b67.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值