差分数组

差分数组学习笔记

差分数组的主要应用场景是对原始数组的某个区间的元素进行增减。例如有一个数组nums,我们需要对nums[2...6]进行+3的操作,对nums[5...8]进行-4的操作,进行多次操作后获得nums数组的值,一般思路即写多个for循环,对目标区间不断进行增减操作,最终得出数组的值,但这种思路时间复杂度为o(n),而且过程十分繁琐,效率低下。此时引入差分数组的概念,类似于前缀和,需要新建一个差分数组diff,diff[i]即为nums[i]-nums[i-1]

vector <int> diff(nums.size())
diff[0]=nums[0];
for(int i=0;i<num.size();i++){
    diff[i]=nums[i]-nums[i-1];
}

有了差分数组diff就可以反推回原数组

vector<int> res(diff.size());
res[0]=diff[0];
for(int i=0;i<diff.size();i++){
    res[i]=res[i-1]+diff[i];
}

构建了了diff数组后,就可以快速的进行区间增减的操作,如果我们相对区间nums[i...j]的元素全部加3,那么只需要让diff[i]+=3,然后再让diff[j+1]-=3即可。其中的原理为diff[i]+=3是给nums的所有元素都加了3,然后diff[j+1]-=3意味着对于nums[j+1...]所有元素再减3,综合起来,就是对nums[i...j]中的所有元素加3。
立体1109航班预定统计问题,
这里有 n 个航班,它们分别从 1 到 n 进行编号。
有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。
请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。

输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号        1   2   3   4   5
预订记录 1 :   10  10
预订记录 2 :       20  20
预订记录 3 :       25  25  25  25
总座位数:      10  55  45  25  25
因此,answer = [10,55,45,25,25]

开始的时候还是没想明白如何转换成差分数组问题,后来观察才明白其实就是对数组进行修改后求和,此时完全符合差分数组的模型,只需要将booking[2]的值加在nums[booking[0]-1]上,然后对nums[]求差分函数变是对数组进行增量运算,再在booking[1]处减去多加的这一份,便完成了对数组的运算,最后再将差分数组还原便可以得出结果。代码如下

#include <vector>
using namespace std;
class Solution
{
public:
    vector<int> corpFlightBookings(vector<vector<int>> &bookings, int n)
    {
        vector<int> nums(n);
        for (auto &booking : bookings)
        {
            nums[booking[0] - 1] += booking[2];
            if (booking[1] < n)
            {
                nums[booking[1]] -= booking[2];
            }
        }
        for (int i = 1; i < n; i++)
        {
            nums[i] += nums[i - 1];
        }
        return nums;
    }
};

leetcode第1094题拼车问题
车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向)给定整数 capacity 和一个数组 trips , trip[i] = [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi 乘客,接他们和放他们的位置分别是 fromi 和 toi 。这些位置是从汽车的初始位置向东的公里数。当且仅当你可以在所有给定的行程中接送所有乘客时,返回 true,否则请返回 false。

输入:trips = [[2,1,5],[3,3,7]], capacity = 4
输出:false
输入:trips = [[2,1,5],[3,3,7]], capacity = 5
输出:true

本题与上一题飞机的题十分相像,不过有一点更简单的就是将数组还原后与空闲位置进行判断后返回即可。虽然代码用时较长而且出了一点小问题,但毕竟是第一次利用所学算法框架自己写出了解决方法,完成了以前未完成的事情,希望今后进步能够越来越快。

#include <vector>
using namespace std;
class Solution
{
public:
    bool carPooling(vector<vector<int>> &trips, int capacity)
    {
        vector<int> nums;
        for (auto &trip : trips)
        {
            nums.resize(1001);
            nums[trip[1]] += trip[0];
            nums[trip[2]] -= trip[0];
        }
        for (int i = 0; i < nums.size(); i++)
        {
            if(i) nums[i] += nums[i - 1];
            if (nums[i] > capacity)
            {
                return false;
            }
        }

        return true;
    }
};

赠诗:

寻隐者不遇
贾岛
松下问童子,言师采药去。
只在此山中,云深不知处。

posted @ 2022-10-11 21:06  ynuiotspx  阅读(98)  评论(0)    收藏  举报