当前位置: 首页 > news >正文

差分 前缀和

根据灵神题单,把前缀和和差分拿出来讲解,大家会了之后记得刷题,容易脑子会了,做不出来题目。

前缀和

前缀和背景

数组中频繁查询某段区间的和,如何优化? 303. 区域和检索 - 数组不可变
前缀和典型

前缀和算法

初步想法

目的:求和 arr[left]+arr[left+1]+arr[left+2]+…+ arr[right]
观察下面的数组

012345
arr[0]arr[0]+arr[1]arr[0]+arr[1]+arr[2]arr[0]+arr[1]+arr[2]+arr[3]arr[0]+arr[1]+arr[2]+arr[3]+arr[4]arr[0]+arr[1]+arr[2]+arr[3]+arr[4]+arr[5]

sum(left,right) = vct[right]-vct[left-1]
注意到,这里要求left >0,需要每次加一个判断,就不是很优雅

加上哨兵

原数组

012345
arr[0]arr[1]arr[2]arr[3]arr[4]arr[5]

加上哨兵

0123456
0arr[0]arr[1]arr[2]arr[3]arr[4]arr[5]

前缀和数组

0123456
0arr[0]arr[0]+arr[1]arr[0]+arr[1]+arr[2]arr[0]+arr[1]+arr[2]+arr[3]arr[0]+arr[1]+arr[2]+arr[3]+arr[4]arr[0]+arr[1]+arr[2]+arr[3]+arr[4]+arr[5]

sum(left,right) = vct[right+1]-vct[left] 就不要做判断了

例题

例题一

303. 区域和检索 - 数组不可变
在这里插入图片描述
解法:


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {int *nums;int numSize;
} NumArray;NumArray *numArrayCreate(int *nums, int numsSize) {NumArray *numArray = (NumArray *)malloc(sizeof(NumArray));numArray->nums     = (int *)malloc(sizeof(int) * (numsSize + 1));numArray->nums[0]  = 0;numArray->numSize  = numsSize+1;memcpy(&numArray->nums[1], nums, numsSize * sizeof(int));for (int i = 1; i < numArray->numSize; i++) {numArray->nums[i] += numArray->nums[i - 1];}return numArray;
}int numArraySumRange(NumArray *obj, int left, int right) {return (obj->nums[right + 1] - obj->nums[left]);
}void numArrayFree(NumArray *obj) {free(obj->nums);obj->nums = NULL;free(obj);
}

例题二

53. 最大子数组和
在这里插入图片描述

超时解法

#include <stdio.h>
#include <stdlib.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
int maxSubArray(int *nums, int numsSize) {int res = nums[0];for (int i = 1; i < numsSize; i++) {nums[i] += nums[i - 1];}for (int left = 0; left < numsSize ; left++) {for (int right = left; right < numsSize; right++) {if (left == 0) {res = max(res, nums[right]);} else {res = max(res, nums[right] - nums[left-1]);}}}return res;
}

复杂度太大了,一直在重复计算最小值

#include <stdio.h>
#include <stdlib.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))
int maxSubArray(int *nums, int numsSize) {int res       = nums[0];int minPreSum = 0;int nowSum    = 0;for (int i = 0; i < numsSize; i++) {nowSum += nums[i];res       = max(res, nowSum - minPreSum);minPreSum = min(minPreSum, nowSum);}return res;
}

正确解法
这里还有一个动态规划的解法

class Solution {
public:int maxSubArray(vector<int> &nums) {int nowRes    = nums.front();int targetRes = nowRes;for (int i = 1; i < nums.size(); i++) {nowRes    = max(nowRes + nums[i], nums[i]);targetRes = max(targetRes, nowRes);//nowRes 表示以nums[i]结尾的,最大子数组和 新的这个最大子数组,要么是nums[i],要么加上之前的值}return targetRes;}
};

例题三

930. 和相同的二元子数组
在这里插入图片描述
解法

class Solution {public:int numSubarraysWithSum(vector<int> &nums, int goal) {unordered_map<int, int> mp;nums.insert(nums.begin(), 0);mp[0]=1;int res = 0;for (int i = 1; i < nums.size(); i++) {nums[i] += nums[i - 1];int targetNum = nums[i] - goal;res += mp[targetNum];mp[nums[i]]++;}return res;}
};

例题四 二维前缀和

二维前缀和解法
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))int **matrixBlockSum(int **mat, int matSize, int *matColSize, int k, int *returnSize,int **returnColumnSizes) {int m = matSize;int n = *matColSize;// Create prefix sum matrix with extra row and column of zerosint **prefixSum = (int **)malloc(sizeof(int *) * (m + 1));for (int i = 0; i <= m; i++) {prefixSum[i] = (int *)calloc(n + 1, sizeof(int));}// Calculate prefix sumsfor (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1] +mat[i - 1][j - 1];}}// Allocate result matrixint **result       = (int **)malloc(sizeof(int *) * m);*returnColumnSizes = (int *)malloc(sizeof(int) * m);*returnSize        = m;for (int i = 0; i < m; i++) {result[i]               = (int *)malloc(sizeof(int) * n);(*returnColumnSizes)[i] = n;for (int j = 0; j < n; j++) {int r1 = max(0, i - k);int c1 = max(0, j - k);int r2 = min(m - 1, i + k);int c2 = min(n - 1, j + k);result[i][j] = prefixSum[r2 + 1][c2 + 1] - prefixSum[r2 + 1][c1] -prefixSum[r1][c2 + 1] + prefixSum[r1][c1];}}// Free prefix sum memoryfor (int i = 0; i <= m; i++) {free(prefixSum[i]);}free(prefixSum);return result;
}

差分

差分原理

原网址
在这里插入图片描述

在这里插入图片描述

例题一

拼车
在这里插入图片描述

#include <stdbool.h>bool carPooling(int **trips, int tripsSize, int *tripsColSize, int capacity) {int vct[1002] = {0};for (int i = 0; i < tripsSize; i++) {vct[trips[i][1]] += trips[i][0];vct[trips[i][2]] -= trips[i][0];}if (vct[0] > capacity) {return false;}for (int i = 1; i < 1002; i++) {vct[i] += vct[i - 1];if (vct[i] > capacity) {return false;}}return true;
}

例题二

2848. 与车相交的点
很简单,类似于合并区间,鉴于数据量比较小,就可以用int存

在这里插入图片描述

例题三

所有排列中的最大和
在这里插入图片描述
根据频率找访问量最大的地方,然后把他给最大的数字

typedef struct {int reqTime;int index;
} Node;int cmp(const void *nodeA, const void *nodeB) {Node *a = (Node *)nodeA;Node *b = (Node *)nodeB;return (a->reqTime > b->reqTime);
}
int cmpInt(const void *nodeA, const void *nodeB) {int a = *(int *)nodeA;int b = *(int *)nodeB;return a > b;
}
int maxSumRangeQuery(int *nums, int numsSize, int **requests, int requestsSize,int *requestsColSize) {Node *vct = (Node *)calloc(sizeof(Node), (numsSize + 2));for (int i = 0; i < requestsSize; i++) {vct[requests[i][0]].reqTime++;vct[requests[i][1] + 1].reqTime--;}vct[0].index = 0;for (int i = 1; i < numsSize; i++) {vct[i].reqTime += vct[i-1].reqTime;vct[i].index = i;}qsort(vct, numsSize, sizeof(Node), cmp);qsort(nums, numsSize, sizeof(int), cmpInt);long long res          = 0;const long long YU_SHU = 1e9 + 7;for (int i = 0; i < numsSize; i++) {res = (res + (long long)vct[i].reqTime * nums[i]) % YU_SHU;}return res;
}
http://www.dtcms.com/a/313300.html

相关文章:

  • 无人机集群协同三维路径规划,采用冠豪猪优化器(Crested Porcupine Optimizer, CPO)实现,Matlab代码
  • 【Django】-8- 视图和模型的关联
  • Linux下Redis常用命令
  • Java线程安全类设计思路总结
  • 深入理解Python的`__missing__`方法:动态处理字典中不存在的键: Effective Python 第18条
  • 网络规划与设计5个阶段内容
  • 大模型学习--第一天
  • Linux命令基础(上)
  • day 44 文件的规范书写与拆分
  • LCL滤波器及其电容电流前馈有源阻尼设计软件【LCLAD_designer】
  • 机器学习——决策树(DecisionTree)
  • 分享两个问题及其解决方法:发送AT没反应和wifi模块连接不上热点
  • Java设计模式之行为型模式(访问者模式)应用场景分析
  • MATLAB小波分析工具包进行时间序列的小波功率谱分析
  • 基于Matlab的深度学习智能行人检测与统计系统
  • FastAPI入门:安全性
  • 网安-逻辑漏洞-23登陆验证
  • 【系统编程】错误处理、读写缓冲区及位图
  • 文章分享---《Keil 再升级,修复了这些bug》
  • [自动化Adapt] 录制引擎
  • Nginx 相关实验(1)
  • C语言数据结构(7)贪吃蛇项目2.贪吃蛇项目实现
  • 分离还是统一,这是个问题
  • STM32F103_Bootloader程序开发13 - 巧用逆向拷贝,实现固件更新的“准原子”操作,无惧升级中的意外掉电
  • 时间空间复杂度
  • 高质量数据集|从武汉光谷《面向科技情报大模型的高质量数据集建设》招标项目谈起
  • 实现游戏排行榜
  • SpringBoot项目数据脱敏(自定义注解)
  • 关于corn
  • SpringAI无人机智能灌溉、本地化AI推理、分析气象站、分析球场草皮系统实践