五月集训 (第08天) —— 前缀和
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五月集训 (第08天) —— 前缀和相关的知识,希望对你有一定的参考价值。
文章目录
前言
此为《英雄算法联盟:算法集训》的内容,具体内容详见:知识星球:英雄算法联盟。加入星球后,即可享用星主 CSDN付费专栏 免费阅读 的权益。
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
希望大家先自己思考,如果实在没有想法,再看下面的算法思路,如果有思路但是写不出来,可以参考朋友圈中其他人的代码,总有一款是适合你的,关注一下他,取其之长,补给之短。
今天集训的内容是:前缀和
前两题较为简单,第三题用C++会非常方便,第四题比较巧妙,如果暂时写不出来,可以先记录下,后续再来做。
一、练习题目
题目链接 | 难度 |
---|---|
1480. 一维数组的动态和 | ★☆☆☆☆ |
1588. 所有奇数长度子数组的和 | ★☆☆☆☆ |
1442. 形成两个异或相等数组的三元组数目 | ★★☆☆☆ |
1094. 拼车 | ★★☆☆☆ |
二、算法思路
1、一维数组的动态和
(1)定义一个用于返回的数组 ret
(2)遍历原数组,如果是第 0 个元素,则直接将它插入待返回的数组;
(3)否则,则将待返回的数组的最后一个元素和当前第 i 个元素加和后插入;
(4)当然,也可以直接在原数组操作,如下:
class Solution
public:
vector<int> runningSum(vector<int>& nums)
for(int i = 1; i < nums.size(); ++i)
nums[i] += nums[i-1];
return nums;
;
2、所有奇数长度子数组的和
(1)首先,定义前缀和 sum;
(2)枚举一个长度 i,枚举一个结束为止 j,利用差分就能得到 sum[j-i+1, j] 的元素和;
(3)统计加和所有 i 为奇数的元素和即可;
class Solution
public:
int sumOddLengthSubarrays(vector<int>& arr)
int i, j, pre, ans = 0;
for(i = 1; i < arr.size(); ++i)
arr[i] += arr[i-1];
for(i = 1; i <= arr.size(); i += 2)
for(j = i-1; j < arr.size(); ++j)
// 以第 j 个数结尾并且长度为 i 的子数组
if(j - i == -1)
pre = 0;
else
pre = arr[j-i];
ans += arr[j] - pre; // arr[j] - arr[j-i]
return ans;
;
3、形成两个异或相等数组的三元组数目
(1)计算前缀和;
(2)枚举一个 j,再枚举 i 将异或和 [i,j-1] 塞入哈希表;
(3)再枚举 k,去哈希表中查找 [j, k] 的异或和并且累加;
(4)时间复杂度可以做到 O(n*n)。
class Solution
unordered_map<int, int> hash;
public:
int countTriplets(vector<int>& arr)
int i, j, k, pre, ans = 0;
for(i = 1; i < arr.size(); ++i)
arr[i] = arr[i-1] ^ arr[i];
for(j = 1; j < arr.size(); ++j)
hash.clear();
for(i = 0; i < j; ++i)
if(i == 0)
pre = 0;
else
pre = arr[i-1];
++hash[ arr[j-1] ^ pre ];
for(k = j; k < arr.size(); ++k)
ans += hash[ arr[k] ^ arr[j-1] ];
return ans;
;
4、拼车
(1)用一个数组来标记上下车的情况;
(2)一次线性扫描置上标记
(3)然后再累加标记,就是当前时间点列车上的人数,如果某个时间点人数超过了给定值,返回 false;一直没有超过,返回 true
class Solution
public:
bool carPooling(vector<vector<int>>& trips, int capacity)
int i, numPassengers[1002];
memset(numPassengers, 0, sizeof(numPassengers));
for(i = 0; i < trips.size(); ++i)
int cnt = trips[i][0];
int l = trips[i][1];
int r = trips[i][2];
numPassengers[l] += cnt;
numPassengers[r] -= cnt;
int sum = 0;
for(i = 0; i <= 1000; ++i)
sum += numPassengers[i];
if(sum > capacity)
return false;
return true;
;
以上是关于五月集训 (第08天) —— 前缀和的主要内容,如果未能解决你的问题,请参考以下文章