首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【优先算法】思还故里闾,欲归道无因 - 前缀和

【优先算法】思还故里闾,欲归道无因 - 前缀和

作者头像
用户11369350
发布于 2025-01-20 11:07:07
发布于 2025-01-20 11:07:07
12000
代码可运行
举报
运行总次数:0
代码可运行

1. 和为K的子数组

题目链接: 560. 和为 K 的子数组

题目描述:

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2 输出:2 示例 2:

输入:nums = [1,2,3], k = 3 输出:2

解法一: 暴力解法

定义计数变量count, 两层循环遍历数组, 每次 j 从 i 的位置开始, 找到满足 [ i , j ] 区间元素和等于k时,count++. 时间复杂度为O(N^2)

解法二: 前缀和 + 哈希表

1. 问题转换并分析

①是 以 i 位置为结尾的子数组,且①满足数组元素为 k. 由此图便可将问题转化为: 当遍历数组到 i 位置时, [ 0 , i-1 ]区间中前缀和为sum[i] - k的个数.

这个时候不要直接去求前缀和数组, 然后遍历找满足条件的前缀和. 如果这么做那时间复杂度还是O(N^2)并且空间复杂度还是O(N), 并不见得比暴力解法要好. 要找前缀和并且其满足sum[i] - k, 可以利用哈希表来找, 哈希表本身就是用来查找的. 哈希表: <前缀和,出现次数>

2. 算法思路

设 i 为数组中的任意位置,用 sum[i] 表示 [0, i] 区间内所有元素的和。 想知道有多少个「以 i 为结尾的和为 k 的子数组」,就要找到有多少个起始位置为 x1, x2, x3… 使得 [x, i] 区间内的所有元素的和为 k 。那么 [0, x] 区间内的和是不是就是 sum[i] - k 了。于是问题就变成: ◦ 找到在 [0, i - 1] 区间内,有多少前缀和等于 sum[i] - k 的即可。

3. 处理细节

1. 我们不用真的初始化一个前缀和数组,因为我们只关心在 i 位置之前,有多少个前缀和等于sum[i] - k 。因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每⼀种前缀和出现的次数。 不要把前缀和都求出来后再加入哈希表, 原本应该是[ 0 , i-1 ] 的前缀和,但求完一并加入 会 使 [ i , n-1] 的前缀和也加进来, 假设[ i , n-1 ] 也有满足条件的前缀和, 就会多算.

2. 如果整个数组和为 k , 那么此时并不存在一个区间让我去找 前缀和 = sum[i] - k, 但是sum[i] = k 这个情况确实存在, 所以在我开始遍历数组之前, 应该先map.put(0,1), sum[i] - k = 0时, 次数赋为1.

4. 代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int subarraySum(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        //将前缀和为0的初始次数设置为1, 因为 k 有可能等于nums数组中某个元素的值.
        map.put(0,1);
        
        int sum = 0,ret = 0;
        for(int x : nums) {
            sum += x;//计算当前位置的前缀和.
            ret += map.getOrDefault(sum-k,0);//统计结果.
            map.put(sum,map.getOrDefault(sum,0)+1);//将当前位置的前缀和sum加入哈希表.
        }
        return ret;
    }
}

2. 和可被 K 整除的⼦数组(蓝桥杯真题)

题目链接: 974. 和可被 K 整除的⼦数组

题目描述:

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的非空 子数组 的数目。

子数组 是数组中 连续 的部分。

示例 1:

输入:nums = [4,5,0,-2,-3,1], k = 5 输出:7 解释: 有 7 个子数组满足其元素之和可被 k = 5 整除: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3] 示例 2:

输入: nums = [5], k = 9 输出: 0

解法一: 暴力枚举

做法与上题基本一致, 就是枚举出所有子数组的和, 时间复杂度为O(N^2).

解法二: 前缀和 + 哈希表

第一点 必要前置知识:

1. 同余定理 如果(a - b) % p = 0 , 那么 a % p = b % p . 即 如果两个数相减的差能被 p 整除,那么这两个数对 p 取模的结果相同. 例如: (7 - 4) % 3 = 0, 7 % 3 = 1, 4 % 3 = 1;

根据同余定理就可以把问题转换成, 在[0 , i-1]区间中找到满足 前缀和 % k 等于 sum[i] % k 的 所有前缀和. (这也是本题的核心.)

2. 负数取模

C++和Java中, 负数 % 正数 结果为 负数, 为了防止 重复算,统一将结果化为正数. 比如 -1 % 3 = -1 换成 (-1 % 3 + 3) % 3 = 2 . 即 a % p -> (a % p + p) % p .

第二: 具体步骤(与上题无异, 不同的是,此题中map第一个位置放的时前缀和 % k 的值. 并且确保是正数.)

设 i 为数组中的任意位置,⽤ sum[i] 表示 [0, i] 区间内所有元素的和。 • 想知道有多少个「以 i 为结尾的可被 k 整除的子数组」,就要找到有多少个起始位置为 x1, x2, x3… 使得 [x, i] 区间内的所有元素的和可被 k 整除。 • 设 [0, x ] (x < i)区间内所有元素之和等于 a , [0, i] 区间内所有元素的和等于 b ,可得 (b - a) % k == 0 。 • 由同余定理可得, [0, x ] 区间与 [0, i] 区间内的前缀和同余。于是问题就变成: ◦ 找到在 [0, i - 1] 区间内,有多少前缀和的余数等于 sum[i] % k 的即可。 我们不用真的初始化⼀个前缀和数组,因为我们只关心在 i 位置之前,有多少个前缀和等于sum[i] - k 。因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每⼀种前缀和出现的次数。

第三 代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int subarraysDivByK(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        map.put(0,1);//还是一样的,[0,i] 当sum = k时,不存在区间,但sum[i] = k存在.
        int sum = 0,ret = 0;
        for(int x : nums) {
            sum += x;//当前位置的前缀和
            int tmp = (sum % k + k) % k;//前缀和模k 的余数,原本是sum % k, 但是Java和C++存在负数模正数等于负数的问题,一并化成正数.
            ret += map.getOrDefault(tmp,0);
            map.put(tmp,map.getOrDefault(tmp,0)+1);
        }
        return ret;
    }
}

3. 连续数组

题目链接: 525. 连续数组

题目描述:

给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。

示例 1:

输入: nums = [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。 示例 2:

输入: nums = [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。

1. 暴力枚举

枚举出所有子数组, 检查子数组是否满足要求,时间复杂度为O(N^2).

2. 前缀和 + 哈希表

第一 问题分析与转换 原数组中的元素只有0和1, 题目要求的是 0 和 1 个数相等的最长子数组, 将所有的 0 换成 -1, 问题就转换成 求 和为0的最长子数组的长度.

第二 处理细节

1. 哈希表<In,In>的两个位置分别存放 [ 0 , i ]前缀和 与 位置 i .

2. 当区间[ 0 , i ]的sum[i] = 0时, 0 < j < i,不存在[0 , j] 区间. 默认一个前缀和为0的情况, 只能以 -1 为结束位置.

3. 如果有重复的sum[ i ] , 保留前面先算出来的 <sum ,i>, 舍弃后面的, 因为先算出来的更靠左边, 离 i 的距离更大, 本题要求的就是最大长度.

第三 步骤

设 i 为数组中的任意位置,⽤ sum[i] 表⽰ [0, i] 区间内所有元素的和。 想知道最⼤的「以 i 为结尾的和为 0 的⼦数组」,就要找到从左往右第⼀个 x1 使得 [x1, i]区间内的所有元素的和为 0 。那么 [0, x1 - 1] 区间内的和是不是就是 sum[i] 了。于是问题 就变成: • 找到在 [0, i - 1] 区间内,第⼀次出现 sum[i] 的位置即可。 我们不⽤真的初始化⼀个前缀和数组,因为我们只关⼼在 i 位置之前,第⼀个前缀和等于 sum[i]的位置。因此,我们仅需⽤⼀个哈希表,⼀边求当前位置的前缀和,⼀边记录第⼀次出现该前缀和的 位置。

第四 代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int findMaxLength(int[] nums) {
       Map<Integer,Integer> hash = new HashMap<>();
       hash.put(0,-1); //当[0,i]sum = 0时,默认存在一个前缀和为0的情况.并且以-1为结束位置.

       int sum = 0,ret = 0;
       for(int i = 0;i < nums.length;++i) {
        if(nums[i] == 0) {
            sum += -1; //将数组中所有的 0 替换成 -1.
        }else {
            sum += nums[i];//求出当前位置的前缀和
        }
        if(hash.containsKey(sum-0)) {
            ret = Math.max(ret,i - hash.get(sum));

        }else{//有重复的只保留前面的那一对<sum,i>.  
            hash.put(sum,i);
        }
       }
       return ret;
    }
}

4. 矩阵区域和

题目链接: 1314. 矩阵区域和

题目描述:

给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:

i - k <= r <= i + k, j - k <= c <= j + k 且 (r, c) 在矩阵内。

示例 1:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1 输出:[[12,21,16],[27,45,33],[24,39,28]] 示例 2:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2 输出:[[45,45,45],[45,45,45],[45,45,45]]

提示:

m == mat.length n == mat[i].length 1 <= m, n, k <= 100 1 <= mat[i][j] <= 100

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Ubuntu 18.04上安装cuda「建议收藏」
$ lspci | grep -i nvidia 我的显示为Tesla P800
全栈程序员站长
2022/09/28
2.2K0
Ubuntu 18.04上安装cuda「建议收藏」
tensorflow-gpu版安装
需要环境 Anaconda CUDA cuDNN 注:tensorflow1.4用的是cuda8,cudnn6;tensorflow用的是cuda9,cudnn7,选择版本时要注意 CUDA安装 首
听城
2018/04/27
8680
tensorflow-gpu版安装
CUDA、CUDNN在windows下的安装及配置
全网最详细 | Windows 安装 TensorFlow2.0 GPU 详细教程
全栈程序员站长
2022/07/02
12.7K0
CUDA、CUDNN在windows下的安装及配置
安装Tensorflow-gpu版本
**下载cuda** **链接:**https://developer.nvidia.com/cuda-10.0-download-archive?target_os=Windows&target_a
陶陶name
2022/05/13
8510
『带你学AI』极简安装TensorFlow2.x的CPU与GPU版本教程
本篇文章就带领大家用最简单地方式安装TF2.0正式版本(CPU与GPU),由我来踩坑,方便大家体验正式版本的TF2.0。
小宋是呢
2022/01/21
3.2K0
『带你学AI』极简安装TensorFlow2.x的CPU与GPU版本教程
Linux & Windows TensorFlow 1.14 升级 2.2
准备尝试升级TensorFlow 1.14 到2.2,需要同时升级本地和服务器的环境,本文记录主要过程。 环境需求 当前TensorFlow最高版本 2.2.+ ,需要CUDA 10.1,cudnn 7.6 官网下载 :https://developer.nvidia.com/ 显卡驱动需要满足CUDA版本要求 CUDA与显卡驱动:https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html TensorFlow-GPU
为为为什么
2022/08/05
6260
ubuntu16.04 部署GPU环境
参考文档 https://blog.csdn.net/nwpushuai/article/details/79935740 https://blog.csdn.net/qq_43030766/article/details/91513501 https://blog.csdn.net/zhqh100/article/details/77646497 https://www.cnblogs.com/zixuan-L/p/11023051.html https://blog.csdn.net/huangfei
三杯水Plus
2019/09/23
6540
win10下安装GPU版本的TensorFlow(cuda + cudnn)
搭了将近快两天的环境,终于好了,虽然在开始的时候,安了卸,卸了安的,但是!!!安装成功后,那种快乐是无法言语的~~~~~所以在此我必须的记录一下我的艰辛历程~~~~
andrew_a
2019/07/30
7.1K1
win10下安装GPU版本的TensorFlow(cuda + cudnn)
ubuntu系统使用Anaconda安装tensorflow-gpu环境
安装tensorflow-gpu,需特别注意tensorflow-gpu、Python、CUDA、cuDNN版本的适配信息,版本不适配会导致tensorflow-gpu安装失败,该安装教程选择的软件版本信息为:ubuntu18.04 + Anaconda3.5.3.1 + Python3.6.12 + tensorflow-gpu2.2.0 + CUDA10.1 + cuDNN7.6.5
全栈程序员站长
2021/04/13
2.3K0
ubuntu系统使用Anaconda安装tensorflow-gpu环境
Windows下配置TensorFlow-GPU开发环境经验总结
其实TensorFlow有一个别人提供的服务器在用着,不过最近访问不了了,估计给收回去了吧。另外自己的MacBook Pro也其实有TensorFlow,但是这个MacBook Pro是二手的,3000块钱收的,而这个本子在前任主人那里也得呆了2年左右了,虽然不长但也有点小卡,尤其是硬盘容量实在是……随便放点东西就基本满了,像我除了写代码还有一些多媒体制作的小事会有,这玩意一两个就占硬盘好几个G……于是,综上原因,因为要学习深度学习,对硬件有一定的要求,因此就萌生了配一台PC主机的想法了。
ZNing
2020/05/13
2.1K0
Windows下配置TensorFlow-GPU开发环境经验总结
Ubuntu17.04安装TensorFlow1.2的GPU版本
本文介绍了在Ubuntu 17.04系统上安装TensorFlow 1.2的GPU版本的过程,包括安装NVIDIA的GPU-CUDA, cuDNN, libcupti-dev, 以及通过pip或spip安装TensorFlow-GPU版本。
王小雷
2018/01/02
1.4K0
Ubuntu17.04安装TensorFlow1.2的GPU版本
Win10系统下Pytorch1.7 + tensorflow2.x +CUDA10.1 安装与配置
最近把tensorflow跟pytorch都重新安装了,发现我以前安装的CUDA10.0的版本无法跟tensorflow2.x适配了,于是我又重新卸载安装了CUDA10.1 +cuDNN8.0.x的版本,然后发现我的Win10上又跟以前一样可以运行tensorflow或者pytorch了。下面就说一下我是如何在Windows 10系统下完成这些配置的。首先看一下软件版本信息:
OpenCV学堂
2021/04/21
1.2K0
Win10系统下Pytorch1.7 + tensorflow2.x +CUDA10.1 安装与配置
一文上手Tensorflow2.0(四)
【磐创AI导读】:本系列文章介绍了与tensorflow的相关知识,包括其介绍、安装及使用等。本篇文章是本系列文章的最后一篇。查看上篇:一文上手Tensorflow2.0之tf.keras|三。在文末作者给出了答疑群的二维码,有疑问的读者可以进群提问。想要获取更多的机器学习、深度学习资源,欢迎大家点击上方蓝字关注我们的公众号:磐创AI。
磐创AI
2019/08/23
1.6K0
win10安装tensorflow-gp
亲测,TensorFlow-gpu1.13.1支持cuda10.0的版本,所以我们可直接选择cuda10.0的版本
py3study
2020/01/16
9070
win10安装tensorflow-gp
Ubuntu18.04完美搭建Tensorflow-gpu
Persist in sharing and promote mutual progress
公众号guangcity
2019/09/20
3.4K0
Ubuntu18.04完美搭建Tensorflow-gpu
TensorFlow-Gpu 1.8安装
终于又到周末了,大家周末快乐,我们都知道在数据挖掘里面有个比赛:Kaggle,这两天在玩Kaggle比赛之泰坦尼克号问题,在下面几节将会详细介绍,泰坦尼克号问题思路及Kaggle比赛玩法。我们一起来期待吧! 这个是当前的成绩:
公众号guangcity
2019/09/20
1.3K0
TensorFlow-Gpu 1.8安装
TensorFlow 2.x GPU版在conda虚拟环境下安装步骤
如果显示都成功找到GPU了,还报错,可能是你的显卡太旧了,尝试降低 tf 版本,或者换显卡,也有可能,显存不够,你可以调小点 batch_size
Michael阿明
2021/02/19
1.5K0
用GPU加速深度学习: Windows安装CUDA+TensorFlow教程
背景 在Windows上使用GPU进行深度学习一直都不是主流,我们一般都首选Linux作为深度学习操作系统。但很多朋友如果只是想要了解深度学习,似乎没有必要专门装双系统或者改用Linux。现实生活中,很多使用学校或者公司电脑的朋友也没有操作权限改换系统。那么到底是否可以在Windows系统上设置深度学习框架,开发深度学习模型呢? 好消息是越来越多的深度学习框架开始支持Windows,这使得在Windows上使用GPU加速学习过程也变成了可能。很多朋友虽然没有一块很强劲的显卡,但也可以以较低的代价来了解在
AI研习社
2018/03/16
13.6K0
用GPU加速深度学习: Windows安装CUDA+TensorFlow教程
双显卡笔记本安装CUDA+theano、tensorflow环境
原文出处:http://www.cnblogs.com/jacklu/p/6377820.html
用户7043923
2020/03/12
9230
Ubuntu18.04LTS下cuda10.0+cudnn7.5+TensorFlow1.13环境搭建
前言 之前写过cuda环境的搭建文章, 这次干脆补全整个深度学习环境的搭建. ---- 开发环境一览 CPU: Intel core i7 4700MQ GPU: NVIDIA GT 750M
sean_yang
2019/03/15
2K0
Ubuntu18.04LTS下cuda10.0+cudnn7.5+TensorFlow1.13环境搭建
相关推荐
Ubuntu 18.04上安装cuda「建议收藏」
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验