每日算法刷题Day42 7.5:leetcode前缀和3道题,用时2h

7. 3026.最大好子数组和(中等,学习)

3026. 最大好子数组和 - 力扣(LeetCode)

思想

1.给你一个长度为 n 的数组 nums 和一个 整数 k

如果 nums 的一个子数组中,第一个元素和最后一个元素 差的绝对值恰好k ,我们称这个子数组为 的。换句话说,如果子数组 nums[i..j] 满足 |nums[i] - nums[j]| == k ,那么它是一个好子数组。

请你返回 nums 子数组的 最大 和,如果没有好子数组,返回 0

2.此题|nums[i] - nums[j]| == k,既可以枚举nums[j],寻找nums[j]+knums[j]-k,所以哈希表的键为nums[j].要让s[j+1]-s[i]最大,此时s[j+1]是固定的,所以要让s[i]最小,所以哈希表的值为同一个nums[i]下最小的s[i](不包括nums[i],所以先更新哈希表再更新s)(学习如何确定的思想)

代码

c++:

复制代码
class Solution {
public:
    long long maximumSubarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        vector<long long> s(n + 1);
        s[0] = 0;
        for (int i = 0; i < n; ++i)
            s[i + 1] = s[i] + nums[i];
        long long res = LONG_MIN;
        map<int, long long> mp; // nums[i]-相同nums[i]下s[i]的最小值
        for (int j = 0; j < n; ++j) {
            auto it1 = mp.find(nums[j] + k);
            auto it2 = mp.find(nums[j] - k);
            if (it1 != mp.end())
                res = max(res, s[j + 1] - it1->second);
            if (it2 != mp.end())
                res = max(res, s[j + 1] - it2->second);
            auto it3 = mp.find(nums[j]);
            if (it3 == mp.end() || s[j] < it3->second)
                mp[nums[j]] = s[j];
        }
        if (res == LONG_MIN)
            return 0;
        return res;
    }
};

优化成一个变量,先更新哈希表再更新s

复制代码
class Solution {
public:
    long long maximumSubarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        long long s = 0;
        long long res = LONG_MIN;
        map<int, long long>
            mp; // nums[i]-相同nums[i]下s[i]的最小值(此时的nums[i]不包括nums[i],所以先更新哈希表再更新s)
        for (auto& x : nums) {
            auto it1 = mp.find(x + k);
            auto it2 = mp.find(x - k);
            if (it1 != mp.end())
                res = max(res, s + x - it1->second);
            if (it2 != mp.end())
                res = max(res, s + x - it2->second);
            auto it3 = mp.find(x);
            // 先不包括nums[i]
            if (it3 == mp.end() || s < it3->second)
                mp[x] = s;
            s += x;
        }
        if (res == LONG_MIN)
            return 0;
        return res;
    }
};
8. 1477.找两个和为目标值且不重叠的子数组(中等,动态规划,之后再做)

1477. 找两个和为目标值且不重叠的子数组 - 力扣(LeetCode)

思想
代码

c++:

复制代码
9. 1546.和为目标值且不重叠的非空子数组的最大数目(中等,细节处理)

1546. 和为目标值且不重叠的非空子数组的最大数目 - 力扣(LeetCode)

思想

1.给你一个数组 nums 和一个整数 target

请你返回 非空不重叠 子数组的最大数目,且每个子数组中数字和都为 target

2.思路没有问题,对于区间[l,r),要让s[r]-s[l]=target,即s[l]=s[r]-target,所以哈希表的键为s[r],因为要不重叠,所以采取贪心思想,记录前一个区间的右 端点end,哈希表的值为 端点下标,此时的区间[it->second,i)

代码

c++:

复制代码
class Solution {
public:
    int maxNonOverlapping(vector<int>& nums, int target) {
        int n = nums.size();
        int s = 0;
        map<int, int> mp; // s[i]-i
        mp[0] = 0;
        int cnt = 0;
        int end = -1;
        for (int i = 1; i <= n; ++i) {
            s += nums[i - 1]; // s[i]
            auto it = mp.find(s - target);
            if (it != mp.end()) {
                // [,end)与[it->second,i)不重叠
                if (end <= it->second) {
                    ++cnt;
                    end = i;
                }
            }
            mp[s] = i;
        }
        return cnt;
    }
};
10. 1124.表现良好的最长时间段(中等,单调栈待学习)

1124. 表现良好的最长时间段 - 力扣(LeetCode)

思想
代码

c++:

复制代码
11. 3381.长度可被K整除的子数组的最大元素和(中等,学习)

3381. 长度可被 K 整除的子数组的最大元素和 - 力扣(LeetCode)

思想

1.给你一个整数数组 nums 和一个整数 k

返回 nums 中一个 非空子数组 的 最大 和,要求该子数组的长度可以 k 整除

2.区间[l,r),即(r-l)%k=0,即r%k=l%k,所以哈希表的键为j%k,要让s[r]-s[l]最大,所以哈希表的值为min(s[i]),遍历前缀和数组,先更新答案,再更新哈希表,因为是取余,所以可以开长度为k的数组,初始值为LLONG_MAX/2,防止减法溢出

代码

c++:

复制代码
class Solution {
public:
    long long maxSubarraySum(vector<int>& nums, int k) {
        int n=nums.size();
        vector<long long> s(n+1);
        for(int i=0;i<n;++i)    s[i+1]=s[i]+nums[i];
        long long res=LLONG_MIN;
        vector<long long> minS(k,LLONG_MAX/2);
        // 遍历前缀和数组
        for(int j=0;j<=n;++j){
            int mod=j%k;
            res=max(res,s[j]-minS[mod]);
            minS[mod]=min(minS[mod],s[j]);
        }
        return res;
    }
};
\*
		map<int,long long> mp;
		// 遍历前缀和数组
		for (int j = 0; j <= n; ++j) {
			int mod = j % k;
			auto it=mp.find(mod);
			if(it!=mp.end()){
				res=max(res,s[j]-it->second);
			}
			if(it==mp.end() || s[j]<it->second) mp[mod]=s[j];
		}
*\

单变量s优化:

复制代码
class Solution {
public:
    long long maxSubarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        long long s = 0;
        long long res = LLONG_MIN;
        map<int, long long> mp; // 下标-值
        mp[k - 1] = 0;          // 前缀和第一个元素为0,下标为-1,取余k为k-1
        for (int j = 0; j < n; ++j) {
            s += nums[j];
            int mod = j % k;
            auto it = mp.find(mod);
            if (it != mp.end()) {
                res = max(res, s - it->second);
            }
            if (it == mp.end() || s < it->second)
                mp[mod] = s;
        }
        return res;
    }
};
相关推荐
森焱森16 分钟前
水下航行器外形分类详解
c语言·单片机·算法·架构·无人机
QuantumStack2 小时前
【C++ 真题】P1104 生日
开发语言·c++·算法
写个博客3 小时前
暑假算法日记第一天
算法
绿皮的猪猪侠3 小时前
算法笔记上机训练实战指南刷题
笔记·算法·pta·上机·浙大
hie988944 小时前
MATLAB锂离子电池伪二维(P2D)模型实现
人工智能·算法·matlab
杰克尼4 小时前
BM5 合并k个已排序的链表
数据结构·算法·链表
.30-06Springfield4 小时前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习
我不是哆啦A梦4 小时前
破解风电运维“百模大战”困局,机械版ChatGPT诞生?
运维·人工智能·python·算法·chatgpt
xiaolang_8616_wjl5 小时前
c++文字游戏_闯关打怪
开发语言·数据结构·c++·算法·c++20
small_wh1te_coder5 小时前
硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
linux·c语言·汇编·嵌入式硬件·算法·c