7月算法训练------第六天(滑动窗口)解题报告

7月算法训练------第六天(滑动窗口)解题报告

题目类型:滑动窗口
题目难度:简单

第一题、643. 子数组最大平均数 I

  1. 题目链接:643. 子数组最大平均数 I
  2. 思路分析:
  • 穷举法:
    将窗口长度固定为k,将k个数相加得到和,求和的最大值,然后求平均值。但时间复杂度太高,超出时间限制。
  1. 代码
class Solution {
    public double findMaxAverage(int[] nums, int k) {
        if(nums.length == 1 && k == 1){
            return (double)nums[0];
        }
        double ans = 0;
        int temp, max = Integer.MIN_VALUE;
        for(int i = 0; i <= nums.length - k; i++){
            temp = 0;
            for(int j = i; j < k + i; j++){
                temp += nums[j];
            }
            if(temp > max){
                max = temp;
            }
        }
        ans = max * 1.0 / k;
        return ans;
    }
}
  • 双指针法:
    定义左指针l和右指针r,当r-l+1<k时,就让nums[r]加进sum中;当r-l+1=k时,就让sum求最大值;当r-l+1=k时,就让l++
  1. 代码:
class Solution {
    public double findMaxAverage(int[] nums, int k) {
        double ans = 0;
        int sum = 0, max = Integer.MIN_VALUE;
        int l = 0, r = -1;
        while(r < nums.length - 1){
            r++;
            sum += nums[r];
            while(r - l + 1 > k){
                sum -= nums[l];
                l++;
            }
            if(r - l + 1 == k){
                max = Math.max(max, sum);
            }
        }
        ans = max * 1.0 / k;
        return ans;
    }
}

第二题、718. 最长重复子数组

  1. 题目链接:718. 最长重复子数组
  2. 思路分析:
  • 动态规划:
    动态规划思路十分巧妙:
    我们申请一个二维dp[nums1.length][nums2.length]
    例如,我们用题上的例子:
    [1,2,3,2,1]
    [3,2,1,4,7]
    行头表示nums1,列头表示nums2
    ij其中有一个为0时,按以下规则赋值:
    dp[i][j] = (nums1[i] == nums2[j]) ? 1 : 0;
    ij都不为0时,按以下规则赋值:
    dp[i][j] = (nums1[i] == nums2[j]) ? dp[i-1][j-1] + 1 : 0;
    然后每次求一次最大值。
12321
300100
201020
110003
400000
700000
  1. 代码:
class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int[][] dp = new int[nums1.length][nums2.length];
        int max = 0;
        for(int i = 0; i < nums1.length; i++){
            for(int j = 0; j < nums2.length; j++){
                if(i == 0 || j == 0){
                    dp[i][j] = (nums1[i] == nums2[j]) ? 1 : 0;
                }else{
                    dp[i][j] = (nums1[i] == nums2[j]) ? dp[i-1][j-1] + 1 : 0;
                }
                max = Math.max(max, dp[i][j]);
            }
        }
        return max;
    }
}

第三题、978. 最长湍流子数组

  1. 题目链接:978. 最长湍流子数组
  2. 思路分析:
  • 动态规划:
    我们拿题中的例子:arr = [9,4,2,10,7,8,8,1,9]
    我们先申请一个比arr.length长度小1的int数组flag,我们按以下规则给flag赋值:
    • 如果arr[i]>arr[i+1],那么就给flag[i]0
    • 如果arr[i]<arr[i+1],那么就给flag[i]1
    • 如果arr[i]=arr[i+1],那么就给flag[i]2
      经过这一步,flag={0,0,1,0,1,2,0,1}
      然后我们声明一个dp[flag.length]的数组,
      dp[0]赋初值:
      • 如果flag[0]=2,那么dp[0]=1
      • 如果flag[0]!=2,那么dp[0]=2
    • flag[i] = 2时,dp[i] = 1
    • flag[i] != 2之后,
      • flag[i] != flag[i-1]时,dp[i]=dp[i-1]+1
      • flag[i] = flag[i-1]时,dp[i]=2

经过这一步,dp={2,2,3,4,5,1,2,3};
最后,返回dp的最大值。
3. 代码:

class Solution {
    public int maxTurbulenceSize(int[] arr) {
        if(arr.length < 2) return arr.length;
        int[] flag = new int[arr.length - 1];
        for(int i = 0; i < flag.length; i++){
            if(arr[i] > arr[i+1]){
                flag[i] = 0;
            }else if(arr[i] < arr[i+1]){
                flag[i] = 1;
            }else{
                flag[i] = 2;
            }
        }
        if(flag.length == 1){
            if(flag[0] == 2){
                return 1;
            }else{
                return 2;
            }
        }
        int[] dp = new int[flag.length];
        if(flag[0] == 2){
            dp[0] = 1;
        }else {
            dp[0] = 2;
        }
        for(int i = 1; i < flag.length; i++){
            if(flag[i] == 2){
                dp[i] = 1;
            }else{
                if(flag[i] != flag[i-1]){
                    dp[i] = dp[i-1] + 1;
                }else{
                    dp[i] = 2;
                }
            }
        }
        Arrays.sort(dp);
        return dp[dp.length - 1];
    }
}

第四题、1052. 爱生气的书店老板

  1. 题目链接:1052. 爱生气的书店老板
  2. 思路分析:
  • 我们先将老板不生气的时候顾客数量加起来,得到一个基础的和initSum
  • 然后我们移动这个长度为minutes的窗口,这个窗口内所有老板生气的时候再继续加起来得到第二个和值,得到这个最大值,然后将这个最大值和initSum加起来,就是最终的答案。
  1. 代码:
class Solution {
    public int maxSatisfied(int[] customers, int[] grumpy, int minutes) {
        int initSum = 0;
        for(int i = 0; i < customers.length; i++){
            if(grumpy[i] == 0){
                initSum += customers[i];
            }
        }
        int[] move = new int[customers.length - minutes + 1];
        for(int i = 0; i < customers.length - minutes + 1; i++){
            for(int j = i; j <= i + minutes - 1; j++){
                if(grumpy[j] == 1){
                    move[i] += customers[j];
                }
            }
        }
        Arrays.sort(move);
        return move[move.length - 1] + initSum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值