构建前缀信息——解决子数组问题

通过构建前缀信息来记录最早出现的位置(或最晚出现的位置)是常用的技巧。而前缀信息还有很多

构建种类来解决子数组问题。

1.构建前缀和

vector<int>presum;
void get_prefix(vector<int>nums) {
	presum.assign(nums.size() + 1, 0);
	for (int i = 1; i < nums.size(); i++) {
		presum[i] = presum[i - 1] + nums[i - 1];
	}
}

通常presum[i]来表示nums从0~i-1的数的和;presum[0]设为0,防止越界

2.固定和的最长子数组

给定一个数组,求子数组(子数组是连续的)的和为K的最大长度

每当遍历到一个节点时,若求以此节点为结尾的子数组的最大长度时,只需要找到节点之前前缀和为sum-k的节点最早出现的位置,那么以此节点为结尾的子数组的最大长度为i-pre(前缀和为sum-k的节点的下标)。所以从头遍历每个节点当作结尾节点,求出最大值

#include <iostream>
#include <vector>
#include <map>
using namespace std;
int compute(vector<int>nums,int k){
    map<int,int>rec;
    rec[0]=-1;
    int ans=0;
    int sum=0;
    for(int i=0;i<nums.size();i++){
        sum+=nums[i];
        if(rec.find(sum-k)!=rec.end())
        ans=max(ans,i-rec[sum-k]);
        if(rec.find(sum)==rec.end())
        rec[sum]=i;
    }
    return ans;
}
int main() {
    int a, b;
    cin >> a >> b;
    vector<int>nums(a,0);
    for(int i=0;i<a;i++)
    cin>>nums[i];
    cout<<compute(nums,b)<<endl;
    return 0;

}

 3.和为k的子数组

class Solution {
public:
    int comput(vector<int> nums, int k) {
        int ans = 0;
        int sum = 0;
        unordered_map<int, int> rec;
        rec[0] = 1;
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
            if (rec.find(sum - k) != rec.end())
                ans += rec[sum - k];
            rec[sum] += 1;
        }
        return ans;
    }
    int subarraySum(vector<int>& nums, int k) { return comput(nums, k); }
};

4.正负数相等的最长子数组

#include <iostream>
#include <iterator>
#include <vector>
#include <unordered_map>
using namespace std;
void self_reverse(int& i) {
    if (i == 0)
        i = 0;
    else if (i > 0)
        i = 1;
    else {
        i = -1;
    }
}
int main() {
    int n;
    cin >> n;
    vector<int>nums(n, 0);
    int sum = 0, ans = 0;
    unordered_map<int, int>rec;
    rec[0] = -1;
    for (int i = 0; i < nums.size(); i++) {
        cin >> nums[i];
        self_reverse(nums[i]);
        sum += nums[i];
        if (rec.find(sum) != rec.end())
            ans = max(ans, i - rec[sum]);
        if (rec.find(sum) == rec.end())
            rec[sum] = i;
    }
    cout << ans << endl;
    return 0;
}

5.良好时间段

class Solution {
public:
    int longestWPI(vector<int>& hours) {
        unordered_map<int, int> rec;
        rec[0] = -1;
        int ans = 0, sum = 0;
        for (int i = 0; i < hours.size(); i++) {
            sum += hours[i] <= 8 ? -1 : 1;
            if (sum > 0)
                ans = i + 1;
            else {
                if (rec.find(sum - 1) != rec.end())
                    ans = max(ans, i - rec[sum - 1]);
            }
            if (rec.find(sum) == rec.end())
                rec[sum] = i;
        }
        return ans;
    }
};

 6.余数为零的子数组和

class Solution {
public:
    int minSubarray(vector<int>& nums, int p) {
        unordered_map<int, int> rec;
        rec[0] = -1;
        int allres = 0;
        for (int i = 0; i < nums.size(); i++)
            allres = ((allres + nums[i]) % p);
        if (allres == 0)
            return 0;
        int partres = 0;
        int ans = INT_MAX;
        for (int i = 0; i < nums.size(); i++) {
            partres = (partres + nums[i]) % p;
            if (rec.find((partres - allres + p) % p) != rec.end())
                ans = min(ans, i - rec[(partres - allres + p) % p]);
            rec[partres] = i;
        }
        return ans == nums.size() ? -1 : ans;
    }
};

 7.偶数元音字母数组

class Solution {
public:
    int get_path(char c) {
        if (c == 'a')
            return 0;
        else if (c == 'e')
            return 1;
        else if (c == 'i')
            return 2;
        else if (c == 'o')
            return 3;
        else if (c == 'u')
            return 4;
        else
            return -1;
    }
    int findTheLongestSubstring(string s) {
        vector<int> rec(33, -2);
        rec[0] = -1;
        int ans = 0, cur = 0;
        for (int i = 0; i < s.size(); i++) {
            int path = get_path(s[i]);
            if (path != -1)//如果是-1说明状态不变,但还要继续求长度,因为
                           //非元音字母也算在其最大长度之中
                cur ^= (1 << path);
            if (rec[cur] != -2)
                ans = max(ans, i - rec[cur]);
            else
                rec[cur] = i;
        }
        return ans;
    }
};

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值