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;
}
}