LeetCode技巧篇(一)prefix sum 前缀和

2023-11-01

介绍

前缀和(prefix sum)是算法题中比较实用的一种技巧,当算法题的背景是整数型数组且出现 “子数组和” 或者 “连续的子数组” 既可以考虑使用前缀和来求解会得到不错的效果。
假设给定的数组A各个元素分别为:
在这里插入图片描述
那么我们可以得到一个前缀和数组B,通过累加A[0:i-1]得到B[i]:
在这里插入图片描述
在实现上,可以直接在数组B的基础上累加即可,不需要遍历一遍A。

实例

现在看一道简单的应用,LeetCode 560. Subarray Sum Equals K。题目很简单,找到连续子数组和为K的子数组个数。传统方法是两次循环,时间复杂度O( n 2 n^{2} n2),空间复杂度O(1)。

    public int subarraySum(int[] nums, int k) {
        int count = 0;
        for (int start = 0; start < nums.length; start++) {
            int sum=0;
            for (int end = start; end < nums.length; end++) {
                sum+=nums[end];
                if (sum == k)
                    count++;
            }
        }
        return count;
    }

但是这里如果使用前缀和搭配HashMap可以实现O(n)的时间复杂度。
首先,我们需要得到前缀和数组。
然后遍历前缀和数组,在HashMap找到是否有元素等于sum[i]-k;如果存在,则count+=map.get(sum[i]-k)。
无论存在与否都将当前元素放进map中,并且更新该值的个数。
代码如下:

    public int subarraySum(int[] nums, int k) {
        int count=0;
        HashMap<Integer, Integer> map = new HashMap();
        int sum[] = new int[nums.length+1];
        for(int i=1;i<sum.length;i++){
            sum[i] = sum[i-1] +nums[i-1];
        }
        for(int i=0;i<sum.length;i++){
            if(map.containsKey(sum[i]-k)){
                count+=map.get(sum[i]-k);
            }
            map.put(sum[i],map.getOrDefault(sum[i],0)+1);
        }
        return count;
    }

再看一题换汤不换药的题目,LeetCode 1343. Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold。找到长度为K且平均值不小于阈值的子数组的个数。这里规定了子数组的长度那就更简单了:
首先,得到前缀和数组;
然后遍历前缀和数组,看间隔为k的数组的平均值是否大于等于阈值。
代码如下:

    public int numOfSubarrays(int[] arr, int k, int threshold) {
        int count =0;
        threshold = threshold * k;
        int[] temp = new int[arr.length+1];
        for(int i=1;i<=arr.length;i++){
            temp[i] = temp[i-1] +arr[i-1];
        }
        for(int i=1;i<=temp.length-k;i++){
           if(temp[i+k-1] - temp[i-1]>=threshold) count++;
        }
        return count;
    }

再看一题稍微有点技巧的,LeetCode 974 Subarray Sums Divisible by K。
这题乍一看和前面1343有点像,但是难度明显更大——因为现在没有规定子数组的长度了,所以这里要转换思路。既然要看子数组和能不能被K整除,那么我们把前缀和数组的每一个元素都对K取余,那么要想子数组能被K整除,只有一种可能,那就是余数相同,因为这里要做减法;如果要像LeetCode 1010. Pairs of Songs With Total Durations Divisible by 60一样和能被60整除的话,那就是判断余数之和了。因此这一题可以看成是 前缀和和余数保存结合起来的题目。

    public int subarraysDivByK(int[] A, int K) {
        int arr[] =new int[A.length+1];
        for(int i=1;i<=A.length;i++){
            arr[i] = arr[i-1] +A[i-1];
        }
        int[] count = new int[K];
        for (int x: arr)
        //这里取余可能会返回负值,因此再加一层
            count[(x % K + K) % K]++;
        int ans = 0;
        for (int v: count)
        //假设余数为3的个数有3个,那么可能有3种情况使得子数组和能被K整除
            ans += v * (v - 1) / 2;
        return ans;
    }

总结

一句话,问题里有subarray sum字样,可以试试prefix sum;
如果是要匹配个数,可以搭配HashMap
如果是和能被整除,那么可以尝试记录每个数和目标数相除的余数

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LeetCode技巧篇(一)prefix sum 前缀和 的相关文章

随机推荐

  • 【java学习】EasyExcel的简单使用

    EasyExcel的简单使用 前言 Excel读 1 实体类 2 读监听器与测试类 3 输出结果 Excel写 1 实体类 2 写入Excel的测试类 3 输出结果 填充Excel 1 Excel模板 2 测试类 3 输出结果 前言 Eas
  • JAVA之Thread类

    一 主线程 主线程 执行主方法的线程 main JVM执行main main 会进入到栈内存 JVM会找操作系统开辟一条main方法通向CPU的执行路径 CPu就可以通过这个路径来执行main方法 而这个路径就叫做主 main 线程 单线程
  • pptpd配置参数详解

    在LINUX下搭建PPTPD服务器主要有3个配置文件 分别如下 etc pptpd conf 主配置文件 debug 把所有的debug信息写入系统日志 var log messages option etc ppp options ppt
  • Hadoop是小象——YARN / Split&Block

    了解Hadoop架构 Hadoop可运行于一般的商用服务器上 具有高容错 高可靠性 高扩展性等特点 特别适合写一次 读多次的场景 其架构如下 HDFS 分布式文件存储 可靠性由心跳机制和冗余提供 YARN 分布式资源管理 MapReduce
  • mysql jdbcurl配置_jdbc的URL配置

    Microsoft SQL Server Microsoft SQL Server JDBC Driver 一般用来连接 SQLServer 2000 驱动程序包名 msbase jar mssqlserver jar msutil jar
  • 【金融申请评分卡】目标变量界定

    一 目标变量是什么 目标变量就是假定申请客户的好坏 逻辑回归公式里的Y 先来看下逻辑回归公式 y 11 e z y 1 1 e z
  • c++入门到精通教程 c++11/14/17-王健伟-专题视频课程

    c 入门到精通教程 c 11 14 17 528人已学习 课程介绍 本教程适合那些只有一点点c语言编程知识的新手 也适合那些c 98标准已经掌握的不错但对c 11 14 17新标准基本无所知的c 开发老手 欢迎大家尽早加入学习 请大家从授课
  • 网络流媒体(七)———RTSP

    RTSP协议介绍 RTSP协议的一些分析 一 一些字符串函数的使用 RTSP协议的一些分析 二 printf类似函数 sscanf以及log保存到内存中 printf输入重定位 1 简介 DSP产生的媒体流需要通过网络传送到客户端 如图1
  • python编程遵循哪些规律_Python实操(3):python编程规范

    选择pythoncharm作为Python开发ide也是在网上查了好长时间 这两天了解到visual studio code强大 易用 同时也一直用visual studio做c c 开发 所以决定把以后的开发平台切换到微软系 换平台以后发
  • 前后端分离:SpringBoot项目部署服务器操作步骤详细

    部署后端 SpringBoot到服务器 首先就是对自己项目application yaml进行配置 此处使用过多mysql8 0 spring datasource url jdbc mysql 127 0 0 1 3306 book se
  • 计算机网络笔记and题解

    上次博客就写了一点划分子网和子网掩码相关的计算 然后还要一个重要的五分类编址CIDR 也就是构造超网 无分类编址CIDR Classless Inter Domain Routing 正式名字是无分类域间路由选择 特点 1 CIDR消除了传
  • 秒级数据转化为分钟级数据sql编写

    前言 利用python读取hive 将hive中秒级数据转化为以10分钟为间隔的数据 除时间与设备id外所有字段的值求平均值 代码 连接hive 创建连接通道 并且得到连接通道的钥匙 句柄 conn connect host 地址 port
  • 存储过程解析

    使用存储过程来解决涨工资 涨工资 总裁涨1000 经理涨800 其他人涨400 伪代码 ResultSet rs select empno job from emp While rs next Int eno rs getInt empno
  • Stable diffusion加载safetensors 模型出现Exception: device privateuseone:0 is invalid

    一 问题 博主用CPU硬解 Stable diffusion sd v1 4 ckpt能跑 但换成v1 5 pruned emaonly safetensors等最新格式的模型就出现Exception device privateuseon
  • MATLAB数据可视化

    MATLAB数据可视化 二维绘图 plot命令 plot y plot x y plot x y s 常见的二维绘图常用设置选项 fplot 三维绘图 plot3 mesh 函数 绘制参数网状表面图 surf 函数 绘制三维阴影曲面图 辅助
  • 蓝桥杯:三羊献瑞(答案不唯一)

    目录 题目描述 题目分析 测试用的代码 Java 答案 因为我个人做选择题有把所有可能性列举的习惯 所以我习惯性列举一下 发现答案并不像题目里面说的 三羊献瑞是唯一的 具体看我的测试用例 Test 但是结果呢 题目描述 本题为填空题 只需要
  • 软件测试和软件开发哪个发展更好

    经常有想转IT行业的同学 在了解软件测试和软件开发之后不知道转那个岗位好 今天就系统的 从多个维度来比较软件测试与软件开发 具体包括从基本素质要求 性格要求 入职门槛 知识结构 竞争压力 职业发展 职业前景等 希望能给在选择软件测试与开发朋
  • java设计模式之抽象工厂模式

    什么是抽象工厂设计模式 抽象工厂模式是一种创建型设计模式 它提供了一种创建一系列相关或依赖对象的方法 而无需指定它们具体的类 抽象工厂模式是工厂方法模式的扩展 它使用一组相关的工厂来创建对象 而工厂方法模式只是使用一个单一的工厂 在抽象工厂
  • APP移动端测试+安装+ADB命令的介绍

    重点 app测试的内容 add命令 monkey命令 次重点 模拟器的安装 雷电 夜神 android的自带的模拟器使用 常规测试 真机测试 简单了解云测Testing 腾讯云 在职小伙伴下周演示 了解 市场有的移动端的操作系统有 1 an
  • LeetCode技巧篇(一)prefix sum 前缀和

    介绍 前缀和 prefix sum 是算法题中比较实用的一种技巧 当算法题的背景是整数型数组且出现 子数组和 或者 连续的子数组 既可以考虑使用前缀和来求解会得到不错的效果 假设给定的数组A各个元素分别为 那么我们可以得到一个前缀和数组B