continuous subarray 连续数组

这篇博客详细介绍了与连续数组相关的算法问题,包括寻找连续子数组和等于特定目标值、和的倍数以及最大子数组和等。通过前缀和策略解决数组和的问题,双指针和动态规划方法处理乘积问题。涵盖LeetCode题目LC560、LC523、LC974、LC53、LC713和LC152。
摘要由CSDN通过智能技术生成

一、连续数组的和

1.等于target ( LC 560)

1)题目
Given an array of integers nums and an integer k, return the total number of continuous subarrays whose sum equals to k.
(连续array,有负数,等于某个target)
2)思路
前缀和:a[i]+…+a[j] = s[I] - s[j - 1] = k
遍历每一个数,检查s[i] - k是否存在于之前的前缀和set中,如果存在说明存在 s[I] - s[j - 1] = k; 并且同时存储当前的前缀和。
3)题解

int subarraySum(vector<int>& nums, int k) {
    unordered_map<int, int> hash;
    int sum = 0;
    int res = 0;
    hash[0]++;
    for (int i = 0; i < nums.size(); i++) {
        sum += nums[i];
        res += hash[sum - k];
        hash[sum]++;
    }
    return res;
}

2.连续和等于target的倍数(LC 523)

1)题目
Given an integer array nums and an integer k, return true if nums has a continuous subarray of size at least two whose elements sum up to a multiple of k, or false otherwise.
An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k.
连续array(长度至少为2), 非负数, 等于target的倍数
2)思路

  • 前缀和:我们不关心前缀和的实际大小,只关心他除以target的余数是不是0–只关心每个数除以k的余数,如果两个前缀和除以k的余数相同,那么他们的差除以k的余数为0.
  • 长度至少为2:插入i-2的数

3)题解

bool checkSubarraySum(vector<int>& nums, int k) {
    int s[nums.size() + 1];
    s[0] = 0;
    for (int i = 1; i <= nums.size(); i++) s[i] = s[i - 1] + nums[i - 1];
    unordered_set<int> hash;
    for (int i = 2; i <= nums.size(); i++) {
        hash.insert(s[i - 2] % k);
        if (hash.count(s[i] % k)) return true;
    }
    return false;
}

3.连续和能够整除k(LC 974)

1)题目
Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k.
A subarray is a contiguous part of an array.
连续array(长度最短为1), 有负数, 等于target的倍数
2)思路

  • 前缀和:我们不关心前缀和的实际大小,只关心他除以target的余数是不是0–只关心每个数除以k的余数,如果两个前缀和除以k的余数相同,那么他们的差除以k的余数为0.
  • 负数处理:(s[i]%k+k)%k (一个负数的余数为-1,另一个正数的余数为k-1,这两个数的差是能被k整除的,应该把他们分到一组。
    3)题解
int subarraysDivByK(vector<int>& nums, int k) {
    int res = 0;
    int s[nums.size() + 1];
    s[0] = 0;
    for (int i = 1; i <= nums.size(); i++) {
        s[i] = s[i - 1] + nums[i - 1];
        s[i] = (s[i] % k + k) % k;
    }
    unordered_map<int, int> hash;
    for (int i = 1; i <= nums.size(); i++) {
        hash[s[i - 1]]++;
        if (hash.count(s[i])) res += hash[s[i]];
    }
    return res;
}

4.最大subarray和(LC 53)

1)题目
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
A subarray is a contiguous part of an array.
连续array(长度最短为1), 有负数, 求最大和
2)思路
DP:dp[i] = max(dp[i-1]+nums[i], ,nums[i])
可以优化空间到O(1)
3)题解

int maxSubArray(vector<int>& nums) {
    int m = -1e5;
    int res = -1e5;
    for (int i = 0; i < nums.size(); i++) {
        m = max(m + nums[i], nums[i]);
        res = max(m, res);
    }
    return res;
}

二、连续数组的乘积

1.小于target ( LC 713)

1)题目
Given an array of integers nums and an integer k, return the number of contiguous subarrays where the product of all the elements in the subarray is strictly less than k.
(连续array,正数,小于某个target)
2)思路
双指针,第二个指针每次向后移动一位,如果区间内乘积小于target,则让结果加上此窗口的长度,否则移动第一个指针,使得区间的乘积小于target。
3)题解

int numSubarrayProductLessThanK(vector<int>& nums, int k) {
    int cur = 1;
    int res = 0;
    for (int i = 0, j = 0; j < nums.size(); j++) {
        cur *= nums[j];
        while(i < j && cur >= k) {
            cur /= nums[i];
            i++;
        }
        if(cur < k) res += (j - i + 1);
    }
    return res;
}

2.最大连续乘积 ( LC 152)

1)题目
Given an integer array nums, find a contiguous non-empty subarray within the array that has the largest product, and return the product.
It is guaranteed that the answer will fit in a 32-bit integer.
A subarray is a contiguous subsequence of the array.
2)思路
记录当前最大的正数和最大的负数
3)题解

int maxProduct(vector<int>& nums) {
    int n = nums.size();
    int f = 1, g = 1;
    int res = INT_MIN;
    for (int i = 0; i < n; i++) {
        int temp1 = f * nums[i];
        int temp2 = g * nums[i];
        f = max(nums[i], max(temp1, temp2));
        g = min(nums[i], min(temp1, temp2));
        res = max(res, f);
    }
    return res;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值