【算法集训 | 暑期刷题营】7.16题---前缀和

本文介绍了算法学习的重要性,并通过四道题目详细讲解了前缀和在解决数组问题中的应用,包括寻找左右子数组和相等的中心索引、和可被K整除的子数组、得分小于K的子数组以及寻找特定差值子数组。通过这些实例,展示了前缀和与哈希表、动态规划等技巧的结合,旨在提升算法理解和运用能力。
摘要由CSDN通过智能技术生成

算法集训传送门

  👉引言

在这里插入图片描述

铭记于心
🎉✨🎉我唯一知道的,便是我一无所知🎉✨🎉

💖 ❄️我们的算法之路❄️💖

   众所周知,作为一名合格的程序员,算法 能力 是不可获缺的,并且在算法学习的过程中我们总是能感受到算法的✨魅力✨。
              ☀️🌟短短几行代码,凝聚无数前人智慧;一个普通循环,即是解题之眼🌟☀️
   💝二分,💝贪心,💝并查集,💝二叉树,💝图论,💝深度优先搜索(dfs),💝宽度优先搜索(bfs),💝数论,💝动态规划等等, 路漫漫其修远兮,吾将上下而求索! 希望在此集训中与大家共同进步,有所收获!!!🎉🎉🎉
在这里插入图片描述


今日主题:前缀和


  • 前缀和一般是与 (哈希表、二分、双指针)等结合使用,以优化时间复杂度,很少单独考察

 👉⭐️第一题💎

   ✨题目

       1.左右两边子数组的和相等
在这里插入图片描述

   ✨思路

先求出数组的前缀和,然后当第i个元素为中心坐标时,那么前i-1个元素一定是S[n-1]-nums[i]的1/2,注意需要单独将最左侧为中心坐标的情况单独拿出来

   ✨代码
class Solution {
public:
   int pivotIndex(vector<int>& nums) {
	int n = nums.size();
	vector<int>S(n);
	S[0] = nums[0];
	for (int i = 1; i <n ; i++) {
		S[i]=nums[i] + S[i - 1];
	}
	int end = S[n - 1];
	if(!(end-nums[0])) return 0;
	for (int i = 1; i < n; i++) {
		int te = end-nums[i];
		if (te == 2 * S[i - 1]) {
			return i;
		}
	}
	return -1;
}
};

在这里插入图片描述

 👉⭐️第二题💎

   ✨题目

      2.和可被K整除的子数组
![

   ✨思路

哈希表+统计个数

   ✨代码
class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int, int> record = {{0, 1}};
        int sum = 0, ans = 0;
        for (int elem: nums) {
            sum += elem;
            int modulus = (sum % k + k) % k;
            if (record.count(modulus)) {
                ans += record[modulus];
            }
            ++record[modulus];
        }
        return ans;
    }
};

在这里插入图片描述

 👉⭐️第三题💎

   ✨题目

       3.统计得分小于K的子数组
在这里插入图片描述

   ✨思路

前缀和与最长子数组进行求解

   ✨代码
class Solution:
    def countSubarrays(self, nums: List[int], k: int) -> int:
        size=len(nums)
        sum=[0]*(size+1)
        for i,v in enumerate(nums):
            sum[i+1]=sum[i]+v

        count=0
        st=0
        ed=1
        while st<size:
            while ed<=size:
                if (sum[ed]-sum[st])*(ed-st)<k:
                    count+=ed-st
                    ed+=1                    
                else:
                    break                         
            st+=1            
        return count

在这里插入图片描述

 👉⭐️第四题💎

   ✨题目

      4.Mark the Photographer
在这里插入图片描述
在这里插入图片描述

   ✨思路

通过推理可知,先排序,然后只需比较第i与i+n个元素的差是否至少比x大即可,因为排序之后这种一一对应的位置排放恰恰是可以让相应的差值最大的情况

   ✨代码
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int m, tar;
        cin >> m >> tar;
        int sum = 2 * m;
        vector<int> nums(sum);
        for (int i = 0; i < sum; i++)
        {
            cin >> nums[i];
        }
        int t = 1;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < m; i++)
        {
            if ((nums[i + m] - nums[i]) < tar)
            {
                t = 0;
                break;
            }
        }
        if (t)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    system("pause");
    return 0;
}

在这里插入图片描述


写在最后
相信大家对今天的集训内容的理解与以往已经有很大不同了吧,或许也感受到了算法的魅力,当然这是一定的,路漫漫其修远兮,吾将上下而求索!伙伴们,明天见!在这里插入图片描述

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想new的出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值