前缀和

[Algo] 前缀和

1. 求arr所有子数组中累加和为aim的最长子数组长度

// 1. 求arr所有子数组中累加和为aim的最长子数组长度
// https://www.nowcoder.com/practice/36fb0fd3c656480c92b569258a1223d5
int f1(vector<int> &v, int aim)
{
    unordered_map<int, int> m; // key: 前缀和, value: 最早出现的位置
    m[0] = -1; // 前缀和为0已存在
    int ans = 0, sum = 0;
    for (int i = 0; i < v.size(); i++)
    {
        sum += v[i]; // 记录前缀和
        int target = sum - aim;
        if (m.find(target) != m.end()) ans = max(ans, i - m[target]);
        if (m.find(sum) == m.end()) m[sum] = i;
    }
    return ans;
}

2. 求arr所有子数组中累加和为aim的子数组个数

// 2. 求arr所有子数组中累加和为aim的子数组个数
// https://leetcode.cn/problems/subarray-sum-equals-k/
int f2(vector<int> &v, int aim)
{
    unordered_map<int, int> m; // key: 前缀和, value: 出现的次数
    m[0] = 1; // 前缀和为0已存在
    int ans = 0, sum = 0;
    for (int i = 0; i < v.size(); i++)
    {
        sum += v[i]; // 记录前缀和
        int target = sum - aim;
        if (m.find(target) != m.end()) ans += m[target];
        if (m.find(sum) != m.end()) m[sum]++;
        else m[sum] = 1;
    }
    return ans;
}

3. 表现良好的最长时间段

// 3. 表现良好的最长时间段
// https://leetcode.cn/problems/longest-well-performing-interval/description/
int f3(vector<int> &v)
{
    unordered_map<int, int> m; // key: 前缀和, value: 最早出现的位置
    int ans = 0, sum = 0;
    for (int i = 0; i < v.size(); i++)
    {
        sum += v[i] > 8 ? 1 : -1; // 记录前缀和
        if (sum > 0) ans = i + 1; // (1) 前缀和大于0,直接更新
        else if (m.find(sum - 1) != m.end()) ans = max(ans, i - m[sum - 1]); // (2) 否则找到第一次出现sum-1的位置
        if (sum < 0 && m.find(sum) == m.end()) m[sum] = i;
    }
    return ans;
}

4. 每个元音包含偶数次的最长子字符串

// 4. 每个元音包含偶数次的最长子字符串
// https://leetcode.cn/problems/find-the-longest-substring-containing-vowels-in-even-counts/description/
int encode(char ch)
{
    switch (ch)
    {
        case 'a': return 0;
        case 'e': return 1;
        case 'i': return 2;
        case 'o': return 3;
        case 'u': return 4;
        default: return -1;
    }
}
int f4(string &s)
{
    int map[32]; // key: aeiou的奇偶性状态(1表示计数, 0表示偶数), value: 最早出现的位置
    for (int i = 0; i < 32; i++) map[i] = -2; // -2表示状态没有出现过
    map[0] = -1; // 00000已出现
    int ans = 0, status = 0;
    for (int i = 0; i < s.length(); i++)
    {
        if (encode(s[i]) != -1) status ^= 1 << encode(s[i]);
        // status表示当前的奇偶性状态
        if (map[status] != -2) ans = max(ans, i - map[status]);
        else map[status] = i;
    }
    return ans;
}
posted @ 2024-12-20 15:14  yaoguyuan  阅读(1)  评论(0编辑  收藏  举报