算法:差分数组

差分数组基本内容

首先差分数组看上去是一个高大上的名词,实际上不还是一个数组嘛,差分数组的解题思想实际上就是创建一个数组然后对这个数组进行维护。

定义

定义:对于已知有n个元素的离线数列d,我们可以建立记录它每项与前一项差值的差分数组f:显然,f[1]=d[1]-0=d[1];对于整数i∈[2,n],我们让f[i]=d[i]-d[i-1]。

差分数组形式

差分数组原数组和差分数组形式如下图所示:
在这里插入图片描述

解释:差分数组的每一项是由原数组当前项 - 原数组前一项
本图中差分数组值由来为:

  • diffList[3] = list[3] - list[2] = 4 - 2 = 2
  • diffList[2] = list[2] - list[1] = 2 - 2 = 0
  • diffList[1] = list[1] - list[0] = 2 - 1 = 1
  • diffList[0] = list[0] = 1

它能解决什么问题

快速进行数组区间修改

在这里插入图片描述

与暴力解法相比

对于以上问题的解决的方式使用暴力的遍历数组当然可以得到想要的结果,但是在时间复杂度上,暴力的时间复杂度是O(n)而差分数组可以将时间复杂度O( n )- > O ( 1 ),所以差分数组解法实际上是暴力解法的优化解决方式

解决流程

设给定一个数组为list,求区间[l,r)上每一项同时+1
数组list包含区间[l,r)

  1. 创建一个差分数组 diffList
  2. 将 diffList [ l ] + 1
  3. 将 diffList [ r + 1 ]- 1
  4. 对数组 diffLIs t求前缀和
  5. 将差分数组的每一项都加入到 list 中

经过这五步就可以让区间[l,r)上的每一项同时+1
原因是如果我想让l-r上的每一项都+1那么只需要让差分数组的每一项都加到原数组当中,因为差分数组的每一项都是原数组当前项与原数组上一项的差值,那么只需要找到差分数组即可。
想要找到差分数组只需要这样做:
在这里插入图片描述

即可得到差分数组

差分数组具体题目应用

接下来以一道非常简单的差分数组应用例题演示差分数组是如何优化区间加减的:

题目描述

leetcode 1109. 航班预订统计

这里有 n 个航班,它们分别从 1 到 n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。

请你返回一个长度为 n 的数组 answer,其中 answer[i] 是航班 i 上预订的座位总数。

**示例 1:**

在这里插入图片描述

提示:

1 <= n <= 2 * 10^4
1 <= bookings.length <= 2 * 10^4
bookings[i].length == 3
1 <= firsti <= lasti <= n
1 <= seatsi <= 104

解题思路

两种思路,

  • 第一种是暴力,由于这道题给的时间比较多,所以用暴力勉强可以过。
  • 第二种是差分数组。几乎没有赘余的操作,几乎可以说是一道差分数组的模板题了

解题步骤

由于暴力的方式过于无脑就不讲解了
解释一下差分数组:

  1. 创建一个长度为n的数组
  2. 将给定数组bookings的前两项进行差分操作
  3. 将差分操作后的数组进行 求解前n项前缀和

代码

暴力

	//暴力
	class Solution {
		public int[] corpFlightBookings(int[][] bookings, int n) {
			int[] seats=new int[n];
    		for(int i=0;i<bookings.length;i++){
    			for(int i1=bookings[i][0]-1;i1<bookings[i][1];i1++){
    				seats[i1]+=bookings[i][2];
    			}
    		}
    		return seats;

		}
	}

暴力运行时间:
在这里插入图片描述

差分数组

	//差分数组
	class Solution {
	    public int[] corpFlightBookings(int[][] bookings, int n) {
	    	//1. 创建一个长度为n的数组
	    	int[] seats=new int[n];
	    	for(int i=0;i<bookings.length;i++){
	    	 	//2. 将给定数组bookings的前两项进行差分操作
	    		seats[bookings[i][0]-1]+=bookings[i][2];
                if(bookings[i][1]<n){
                    seats[bookings[i][1]]-=bookings[i][2];
                }
	    		
	    	}
	    	//3. 将差分操作后的数组进行 求解前n项前缀和
	    	for(int i=1;i<n;i++){
	    		seats[i]=seats[i-1]+seats[i];
	    	}
	    	return seats;

	    }
	}
	

差分数组运行时间
在这里插入图片描述
以上就是我对差分数组的理解,欢迎大佬斧正

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值