【七月算法】day06 双指针

643. 子数组最大平均数 I

题目描述:

给你一个由 n 个元素组成的整数数组 nums 和一个整数 k 。

请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。

任何误差小于 10-5 的答案都将被视为正确答案。

思路:

典型双指针题目,注意两点:

1、最大值的初值要设的小一点

2、注意类型转换 int -> double

class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        int sumv = 0;
        int maxv = -10000000001;
        int l = 0, r = -1;
        while (r < (int)nums.size() - 1) {
            ++r;
            sumv += nums[r];
            while (r- l + 1 > k) {
                sumv -= nums[l];
                ++l;
            }
            if (r- l+1 == k) {
                maxv = max(maxv, sumv);
            }
        }

        return maxv*1.0/k;
    }
};

718. 最长重复子数组

题目描述:

给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 

思路:

dp更好做,

定义一个dp数组,dp[i][j] 表示以nums1[i]和nums2[j]结尾的最长公共子串的长度

根据nums1[i]和nums2[j]的实际情况和dp[i-1][j-1]的值进行递推求解;

dp[i][j]是由dp[i-1][j-1]推来的

class Solution {
    int dp[1010][1010]; //dp[i][j] = 1时表示nums1[i]和nums2[j]相等,否则不相等
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        int maxv = -1;
        for (int i = 0; i < nums1.size(); ++i) {
            for (int j = 0; j < nums2.size(); ++j) {
                if (!i || !j) {
                    dp[i][j] = nums1[i] == nums2[j] ? 1 : 0;
                } else {
                    dp[i][j] = nums1[i] == nums2[j] ? dp[i-1][j-1]+1 : 0;
                }
                maxv = max(maxv, dp[i][j]);
            }
        }
        return maxv;

    }
};

978. 最长湍流子数组

题目描述:

给定一个整数数组 arr ,返回 arr 的 最大湍流子数组的长度 。

如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是 湍流子数组 。

更正式地来说,当 arr 的子数组 A[i], A[i+1], ..., A[j] 满足仅满足下列条件时,我们称其为湍流子数组:

若 i <= k < j :
当 k 为奇数时, A[k] > A[k+1],且
当 k 为偶数时,A[k] < A[k+1];
或 若 i <= k < j :
当 k 为偶数时,A[k] > A[k+1] ,且
当 k 为奇数时, A[k] < A[k+1]。

思路:

题目的意思是,数据大小交替出现;

定义两个数组,acd代表序列最后一个元素是递增的最长序列长度,des代表序列最后一个元素是递减的最长序列长度,一次枚举即可;

class Solution {
public:
    int maxTurbulenceSize(vector<int>& arr) {
        int acd[40010], des[40010];
        int ans = 0;
        for (int i = 1; i < arr.size(); ++i) {
            acd[i] = 1;
            des[i] = 1;
            if (i) {
                if (arr[i-1] < arr[i]) {
                    acd[i] = des[i-1]+1;
                } else if (arr[i-1] > arr[i]){
                    des[i] = acd[i-1]+1;
                }
            }
            
            ans = max(ans, max(acd[i], des[i]));
        }

        return ans;

    }
};

1052. 爱生气的书店老板

题目描述:

有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers ,其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。

在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。

当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。

书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。

请你返回 这一天营业下来,最多有多少客户能够感到满意。

思路:

1、记录两个前缀和,一个表示不管生不生气的前缀和,一个表示生气的情况下的前缀和;
2、定义一个滑动窗口进行操作,点那个窗口正好为minutes时,则进行判定;
令考虑生气的情况下的人数为x,当窗口[i,j]的人数,考虑生气的情况下为y,不考虑生气的情况下的人数为z,结果就是x-y+z,计算最大值。其中y和z剋通过前缀差分和求得。

class Solution {
    #define maxn 20010
public:
    int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
        int custSum[maxn];
        int custGru[maxn];
        int n = customers.size();
        //计算前缀和
        for (int i = 1; i <= n; ++i) {
            custSum[i] = custSum[i-1] + customers[i-1];
            custGru[i] = custGru[i-1] + customers[i-1]*(!grumpy[i-1]);
        }
        int i = 1, j = 0, ans = 0;
        while (j < n) {
            ++j;
            while(j - i + 1 > minutes) {
                ++i;
            }
            if (j - i + 1 == minutes) {
                int val = custGru[n] - (custGru[j] - custGru[i-1]) + custSum[j] - custSum[i-1];
                ans = max(ans, val);
            }
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/ilovejujube/article/details/125637531