Leetcode刷题 2021.02.04

Leetcode643 子数组最大平均数 I

给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。

每日一题,和前两天做的那道题很像,就是遍历求和而已。没什么好说的。

class Solution {
    
    
    public double findMaxAverage(int[] nums, int k) {
    
    
        int sum = 0, max = Integer.MIN_VALUE;
        for(int i = 0; i < k - 1; i++){
    
    
            sum += nums[i];
        }
        for(int i = k - 1; i < nums.length; i++){
    
    
            sum += nums[i];
            max = Math.max(max, sum);
            sum -= nums[i - k + 1];
        }

        return (double) max / k;
    }
}

Leetcode1248 统计「优美子数组」

给你一个整数数组 nums 和一个整数 k。

如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。

请返回这个数组中「优美子数组」的数目。

滑动窗口题,首先可以找到正好有k个奇数数字的窗口。然后缩小左窗口,扩大有窗口,得到对应的left,right值,最后子数组的个数即为left*right的值。

class Solution {
    
    
    public int numberOfSubarrays(int[] nums, int k) {
    
    
        int i = 0, j = 0, count = 0, res = 0, n = nums.length;
        while (j < n){
    
    
       	 	//如果为奇数增加count值
            if (nums[j] % 2 != 0) count++;
            //如果奇数值正好等于k
            if (count == k){
    
    
                int left = 0, right = 0;
                //缩小左窗口,计算左边窗口是偶数的数目
                while (nums[i] % 2 == 0){
    
    
                    i++;
                    left++;
                }
                j++;
                //扩大右窗口,计算右边窗口是偶数的数目
                while (j < n && nums[j] % 2 == 0){
    
    
                    j++;
                    right++;
                }
                //子数组的值就是(left + 1) * (right + 1), 比如2,2,1,1,2,2。
                //左边可以选0个或者1个或者2个2,右边同理,那么子数组的个数一共为3 * 3 = 9
                res += (left + 1) * (right + 1);
                count--;
                i++;
            }else{
    
    
                j++;
            }
        }

        return res;

    }
}

Leetcode907 子数组的最小值之和

给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。

由于答案可能很大,因此 返回答案模 10^9 + 7 。

例如:

[2,3,4],中位数是 3
[2,3],中位数是 (2 + 3) / 2 = 2.5
给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

之前没做过类似的题,看了题解才明白。这种数组又是最小值的题,常用的方法就是滑窗,单调栈,dp,或者前缀和等等。还是要多做多练。
这题维护一个单调栈,有比当前栈顶的元素进来之后就计算,以当前栈顶元素为最小值的数组有几个,然后乘以栈顶元素就行了。

class Solution {
    
    
    public int sumSubarrayMins(int[] arr) {
    
    
        int n = arr.length, res = 0;
        int MOD = 1000000007;
        //维护一个单调栈
        Stack<Integer> stack = new Stack<>();
        for(int i = 0; i <= n; i++){
    
    
        	//这题最后压入一个0,保证栈里所有的元素都被弹出了。	
            int temp = i == n ? 0 : arr[i];
            //维护一个单调递增栈
            while (!stack.isEmpty() && temp < arr[stack.peek()]){
    
    
            	//如果当前元素小于栈顶元素,先pop出来
                int index = stack.pop();
                //计算左边元素的个数,判断栈是否已经为空的情况
                int left = index - (stack.isEmpty() ? - 1 : stack.peek());
                //右边元素就是i - idx
                int right = i - index;
                //最后以当前元素为最小值的元素的个数是left * right,再乘以元素值就行了
                //这里取余搞了好久,一直不能通过。。
                res += (long) left * right % MOD * arr[index] % MOD;
                res %= MOD;
            }
            stack.push(i);
        }
        return res;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43447128/article/details/113666519