📌  相关文章
📜  使用Set获得的总和小于或等于给定总和的最大总和子数组(1)

📅  最后修改于: 2023-12-03 15:22:20.966000             🧑  作者: Mango

使用 Set 获得总和小于或等于给定总和的最大总和子数组

在解决算法问题时,我们经常会遇到需要在数组中找到一个子数组,使得子数组的总和小于或等于给定的总和,且最大化子数组的长度。这个问题可以通过使用 Set 数据结构来解决,因为 Set 对于查找操作有很高的效率。

问题描述

给定一个数组 nums 和整数 sum,求一个最大长度的子数组,使得子数组元素的和小于或等于 sum。

算法步骤
  1. 定义 Set 集合 used,用于存储累计和。
  2. 定义变量 curSum 表示当前累计和,初始化为 0。
  3. 定义变量 ans 表示最长子数组的长度,初始化为 0。
  4. 遍历数组 nums,如果当前元素小于或等于 sum,那么将其加到 curSum 中,然后使用 Set 的 lower_bound 方法查找到比 curSum - sum 更小或相等的元素的索引值,如果该索引值存在,那么用当前位置的索引减去对应的 Set 中的元素的索引值,得到的就是以该位置为右端点的最大长度,并更新 ans 的值。
  5. 将 curSum 加入 Set 中。
  6. 返回 ans。
代码实现
int maxSubarrayLen(vector<int>& nums, int sum) {
    int ans = 0;
    unordered_set<int> used;
    used.insert(0);
    int curSum = 0;
    for (int i = 0; i < nums.size(); i++) {
        curSum += nums[i];
        auto it = used.lower_bound(curSum - sum);
        if (it != used.end()) {
            ans = max(ans, i - (*it));
        }
        used.insert(curSum);
    }
    return ans;
}
总结

本算法的时间复杂度为 O(n log n),因为用到了 Set 的 lower_bound 方法。注意,在求解以当前位置为右端点的最大长度时,要使用该位置的索引减去对应的 Set 中的元素的索引值,并非直接减一。写代码时要注意细节。