【路飞】11. 盛最多水的容器、470. 用 Rand7() 实现 Rand10()、239. 滑动窗口最大值

94 阅读3分钟

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。 示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49

示例 2:

输入: height = [1,1]
输出: 1

解题思路:这题的要去其实就是求最大面积,给的数据是高度,宽度是每个高度对应的索引,这题可以用双指针来做,从数组的开头和结尾向中间进行,获取最大面积,那边高度小就向前进一步,代码如下:

var maxArea = function(height) {
    // 设置指针i 和 j 分别从两个端点向中间前进
    let i = 0, j = height.length - 1;
    //默认最大面积是0
    let maxS = 0;
    while( i < j ){
        //获取最小的高度
        let min = Math.min(height[i],height[j]);
        //最小高度乘以两个柱子的宽就是面积
        let s = min * (j - i);
        //更新最大面积
        maxS = s > maxS ? s : maxS;
        //谁小谁向前进
        if(height[i] > height[j]) j --;
        else i ++;
    }
    return maxS;
};

470. 用 Rand7() 实现 Rand10()

给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数,试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数。

你只能调用 rand7() 且不能调用其他方法。请不要使用系统的 Math.random() 方法。

每个测试用例将有一个内部参数 n,即你实现的函数 rand10() 在测试时将被调用的次数。请注意,这不是传递给 rand10() 的参数。

 示例 1:

输入: 1
输出: [2]

示例 2:

输入: 2
输出: [2,8]

示例 3:

输入: 3
输出: [3,8,10]

解题思路:rand2() 就是等概率生成1和2,就是在数组[1,2]随机获取,1和2的概率一样,rand3()在数组[1,2,3],1 2 3的概率一样,[1,2,3] 和 [1,1,2,2,3,3]是一样的因为概率相同,这题要做的就是生成一个数组里面获取一到十的概率一样,比如我们由rand10()变化成rand7(),就是在rand7() 的时候继续随机获取,直到获取到7以下,由推论我们可以得到两个公式小变大(RX - 1)* Y + RY = RXY,大变小就是 RX % R + 1 = RR,大于R的话就重新选择,代码如下:

var rand10 = function() {
    //保持循环遍历,直到找到满足条件的数字,
    while(true){
        //因为我们只能用rand7(),因为我们只能用rand7(),所以这里我们Y都取7,此时num等于 rand49();
        let num = (rand7() - 1) * 7 + rand7();
        //四十以下的对10取余概率是一样的,所以只要小于等于40都是满足rand10();此时大于40的数字都是浪费的,可以知道浪费了9个值
        if(num <= 40) return num % 10 + 1;
        //此时num大于40为了减少浪费可以再转换成rand63(),这样浪费的数字四三个,
        num = (num - 40 - 1) * 7 + rand7();
        if(num <= 60) return num % 10 + 1;
        //此时大于60我们可以转换成rand21(),只浪费1个,
        num = (num - 60 - 1) * 7 + rand7();
        if(num <= 20) return num % 10 + 1;
    }
    return num
};

239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

输入: nums = [1], k = 1
输出: [1]

解题思路:这题的解题思路是,用一个数组来保存滑窗的宽度,然后找出改滑窗最大值,保存起来,然后往后遍历,当遍历范围超出k了就删除滑窗第一个数,代码如下

var maxSlidingWindow = function(nums, k) {
    if(k <= 1) return nums;
    //滑窗的宽度,最大是k
    let q = [];
    //存储最大值
    let ans = [];
    //从数组0开始遍历
    let i = 0;
    while(i < nums.length){
        //当数组存在且刚超出k的时候删除第一个数,保持q存的是i到 i + k之间的值
        if(q.length && q[0] + k <= i) q.shift();
        //遍历查询滑窗内最大值
        while(q.length && nums[q[q.length - 1]] <= nums[i]) q.pop();
        //将当前所有储存在滑窗里
        q.push(i);
        //继续遍历下去
        i ++;
        //当i等于k时第一个最大值出现就是滑窗的第一个值,此后每次都会出现一个最大值
        if(i >= k) ans.push(nums[q[0]]);
    }
    return ans;
};