小而美的算法技巧:差分数组 :: labuladong的算法小抄 #1004
Replies: 50 comments 3 replies
-
|
Beta Was this translation helpful? Give feedback.
-
倒霉了,一遍没看懂/(ㄒoㄒ)/~~ |
Beta Was this translation helpful? Give feedback.
-
0 <= trips[i][1] < trips[i][2] <= 1000 |
Beta Was this translation helpful? Give feedback.
-
@lumaster 感谢指出,文中写错了,我改下 |
Beta Was this translation helpful? Give feedback.
-
多看几遍 上手敲一敲 (自己敲) 理解逻辑 加油! |
Beta Was this translation helpful? Give feedback.
-
好啊,还能刷到收费的题目,赚了赚了,我说我在lc插件和力扣翻了一会儿没看到这题 |
Beta Was this translation helpful? Give feedback.
-
佩服这些设计者的脑子,我可能一辈子都想不到这么秒的方法。 |
Beta Was this translation helpful? Give feedback.
-
这里的原数组 |
Beta Was this translation helpful? Give feedback.
-
如果trips = [[9,0,1]], capacity = 4 |
Beta Was this translation helpful? Give feedback.
-
@jay-zhu 可以,但也不是必须的,最后那个 for 循环会统一检查。 |
Beta Was this translation helpful? Give feedback.
-
看到最多1001的时候震惊了,我竟然用双循环找最大值 |
Beta Was this translation helpful? Give feedback.
-
区间 但是差分数组 一起增大的 差分数组中间不变 只是差分数组的第一个和最后一个 这两个元素不同
|
Beta Was this translation helpful? Give feedback.
-
这里是不是应该注释一下,nums[i] 表示 站点 i 到站点 i+1 之间的乘客人数。由此,虽然有1001个站点,但是 nums 的长度只要 1000 就可以了。 |
Beta Was this translation helpful? Give feedback.
-
发现原来差分数组的前缀和就是原数组!! 其实区间问题可以不用-1,因为你在vec[ 2 ]-1之后 又在后面修改判断 j+1 是不是越界,然后又让 j+1 |
Beta Was this translation helpful? Give feedback.
-
1109题我感觉你说的还是挺明白的,但是1094拼车那道题 |
Beta Was this translation helpful? Give feedback.
-
打卡,附上详细代码//拼车的代码
//定义的一个差分数组类,这个类里面主要包括两个主要的方法,一个是更新数组中一个范围的数,另一个方法是返回更新后的数组的结果
class Difference {
//差分数组
private int[] diff;
public Difference(int[] nums) {
int n=nums.length;
if(n<=0){
return;
}
//构造差分数组
diff=new int[n];
diff[0]=nums[0];
for (int i = 1; i <n ; i++) {
diff[i]=nums[i]-nums[i-1];
}
}
//在i-j这个范围内,对数据进行val更新操作,val可以是负值
public void incr(int i,int j,int val){
diff[i]+=val;
//如果j+1超过了数组的范围说明我们是对i到最后的位置进行了更新,所以j后面的就不需要再减val了
if(j+1<diff.length){
diff[j+1]-=val;
}
}
//返回更新后的数组
public int[] result(){
int[] res=new int[diff.length];
res[0]=diff[0];
for (int i = 1; i < diff.length ; i++) {
res[i]=res[i-1]+diff[i];
}
return res;
}
}
public boolean carPooling(int[][] trips, int capacity) {
int[] nums=new int[1001];
Difference difference=new Difference(nums);
for (int[] trip : trips) {
int i=trip[1];
//这里为什么减一,因为到了j位置的时候旅客就下车了
int j=trip[2]-1;
//上车的人数
int val=trip[0];
difference.incr(i,j,val);
}
int[] result = difference.result();
for (int i = 0; i < result.length; i++) {
//我们必须保证在开车的整个过程中,车上的人数不能超过最大载客量也就是capacity
if(result[i]>capacity){
return false;
}
}
return true;
}
//=========================飞机的代码
//定义的一个差分数组类,这个类里面主要包括两个主要的方法,一个是更新数组中一个范围的数,另一个方法是返回更新后的数组的结果
class Difference {
//差分数组
private int[] diff;
public Difference(int[] nums) {
int n=nums.length;
if(n<=0){
return;
}
//构造差分数组
diff=new int[n];
diff[0]=nums[0];
for (int i = 1; i <n ; i++) {
diff[i]=nums[i]-nums[i-1];
}
}
//在i-j这个范围内,对数据进行val更新操作,val可以是负值
public void incr(int i,int j,int val){
diff[i]+=val;
if(j+1<diff.length){
diff[j+1]-=val;
}
}
//返回更新后的数组
public int[] result(){
int[] res=new int[diff.length];
res[0]=diff[0];
for (int i = 1; i < diff.length ; i++) {
res[i]=res[i-1]+diff[i];
}
return res;
}
}
public int[] corpFlightBookings(int[][] bookings, int n) {
int[] nums=new int[n];
Difference difference=new Difference(nums);
for (int[] booking : bookings) {
//题目中描述下标从1开始,因为数组下标从0开始,所以我们要减1
int i=booking[0]-1;
int j=booking[1]-1;
int val=booking[2];
difference.incr(i,j,val);
}
return difference.result();
} |
Beta Was this translation helpful? Give feedback.
-
拼车最后遍历长度为1001的result,其实后边有很多都是0,加一个全局变量记录一下最后下车位置,就不用遍历所有车站了,代码如下
|
Beta Was this translation helpful? Give feedback.
-
1094.拼车 python打卡 class Solution:
def carPooling(self, trips: List[List[int]], capacity: int) -> bool:
nums=[0]*1001
df=Difference(nums)
for trip in trips:
num=trip[0]
start=trip[1]
end=trip[2]-1
df.increment(start,end,num)
res=df.result()
for r in res:
if r>capacity:
return False
return True
class Difference():
def __init__(self,nums:List[int]):
self.nums=nums
self.diff=[0]*len(nums)
self.diff[0]=nums[0]
for i in range(1,len(nums)):
self.diff[i]=nums[i]-nums[i-1]
def increment(self,i,j,val):
self.diff[i]+=val
if (j+1)<len(self.diff):
self.diff[j+1]-=val
def result(self):
res=[0]*len(self.diff)
res[0]=self.diff[0]
for i in range(1,len(self.nums)):
res[i]=res[i-1]+self.diff[i]
return res |
Beta Was this translation helpful? Give feedback.
-
1109.航班预定统计 python打卡
|
Beta Was this translation helpful? Give feedback.
-
diff = [0] * len(nums)
# 构造差分数组
diff[0] = nums[0]
for i in range(1, len(nums)):
diff[i] = nums[i] - nums[i - 1]
# 从这里可以直接反推出得到原始数组的等式
# nums[i] = diff[i] + nums[i-1] 由等式
|
Beta Was this translation helpful? Give feedback.
-
对于各类「区间求和」问题(加粗字体为最佳方案): 数组不变,区间查询:前缀和、树状数组、线段树; 对于各类「区间求和」问题,该用什么方式进行求解,之前在 这里 提到过。 |
Beta Was this translation helpful? Give feedback.
-
计算累加和大佬写错了吧: // 计算 nums 的累加和 应该是下面这样写吧, 要不然preSum数组没有填满 |
Beta Was this translation helpful? Give feedback.
-
注意点:飞机那道题的下标是从1开始的,大巴车的下标是从0开始的! |
Beta Was this translation helpful? Give feedback.
-
拼车内存优化 其实可以先遍历一遍trips找到测试用例中最大的toi,构造长度为最大toi+1的数组,因为最大toi之后车子是空载的。 虽然多遍历了一遍trips,但后续“判断每公里是否超载”的时候,数组长度小了>遍历次数少了,时间也会适当地减少。 |
Beta Was this translation helpful? Give feedback.
-
当 j+1 >= diff.length 时,说明是对 nums[i] 及以后的整个数组都进行修改,那么就不需要再给 diff 数组减 val 了。请问这句话怎么理解不太懂 |
Beta Was this translation helpful? Give feedback.
-
可以计算出最大的下客车站,len就用最大的下客车+1.这样可以节省空间,时间反而更快 |
Beta Was this translation helpful? Give feedback.
-
为啥文章代码里面创建df对象时候只传递了一个参数? |
Beta Was this translation helpful? Give feedback.
-
文章链接点这里:小而美的算法技巧:差分数组
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions