标签 子串 下的文章

题目链接:滑动窗口最大值

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

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

方法:单调队列

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if (nums.size() == 0 || k == 0) return {};
        deque<int> d;
        vector<int> res(nums.size()-k+1);
        for (int j = 0,i = 1-k; j < nums.size();i++,j++) {
            if (i > 0 && d.front() == nums[i-1]) {
                d.pop_front();
            }
            while (!d.empty() && d.back() < nums[j]) 
                d.pop_back();
            d.push_back(nums[j]);
            if (i >= 0) {
                res[i] = d.front();
            }

        }
        return res;
    }
};

题目链接:和为 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

子数组是数组中元素的连续非空序列。

方法一:前缀和+暴力

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        vector<int> nu(nums.size()+1);
        nu[0] = 0;
        int ans = 0;
        for (int i = 1;i <= nums.size();i++) {
            nu[i] = nums[i-1] + nu[i-1];
        }
        for (int i = 1;i <= nums.size();i++) {
            for (int j = 0;j < i;j++) {
                if (nu[i] - nu[j] == k) {
                    ans++;
                } 
            }
        }
        return ans;
    }
};

方法二:前缀和+哈希表

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        // key: 前缀和   value: 这个前缀和出现的次数
        unordered_map<long long, int> cnt;
        cnt[0] = 1; // 前缀和为 0 的情况(什么都没取),出现 1 次

        long long sum = 0; // 当前前缀和,用 long long 更安全
        int ans = 0;

        for (int x : nums) {
            sum += x;                 // 更新前缀和
            long long need = sum - k; // 需要的前缀和

            // 如果之前有前缀和等于 sum - k,说明存在若干子数组和为 k
            if (cnt.count(need)) {
                ans += cnt[need];
            }

            // 把当前前缀和加入哈希表
            cnt[sum]++;
        }

        return ans;
    }
};