leetcode刷题(111)——1109. 航班预订统计

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

我们这儿有一份航班预订表,表中第 i 条预订记录 bookings[i] = [j, k, l] 意味着我们在从 j 到 k 的每个航班上预订了 l 个座位。

请你返回一个长度为 n 的数组 answer,按航班编号顺序返回每个航班上预订的座位数。

示例:

输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]

可以使用差分数组差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。

比如说,我给你输入一个数组nums,然后又要求给区间nums[2…6]全部加 1,再给nums[3…9]全部减 3,再给nums[0…4]全部加 2,再给…

高效的解决方法:
我们先对nums数组构造一个diff差分数组,diff[i]就是nums[i]和nums[i-1]之差:

int[] diff = new int[nums.length];
// 构造差分数组
diff[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
    
    
    diff[i] = nums[i] - nums[i - 1];
}

在这里插入图片描述
这样构造差分数组diff,就可以快速进行区间增减的操作,如果你想对区间nums[i…j]的元素全部加 3,那么只需要让diff[i] += 3,然后再让diff[j+1] -= 3即可:
在这里插入图片描述
原理很简单,回想diff数组反推nums数组的过程,diff[i] += 3意味着给nums[i…]所有的元素都加了 3,然后diff[j+1] -= 3又意味着对于nums[j+1…]所有元素再减 3,那综合起来,是不是就是对nums[i…j]中的所有元素都加 3 了?

class Difference {
    
    
    // 差分数组
    private int[] diff;

    public Difference(int[] nums) {
    
    
        assert nums.length > 0;
        diff = new int[nums.length];
        // 构造差分数组
        diff[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
    
    
            diff[i] = nums[i] - nums[i - 1];
        }
    }

    /* 给闭区间 [i,j] 增加 val(可以是负数)*/
    public void increment(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;
    }
}

这里注意一下increment方法中的 if 语句:

public void increment(int i, int j, int val) {
    
    
    diff[i] += val;
    if (j + 1 < diff.length) {
    
    
        diff[j + 1] -= val;
    }
}

当j+1 >= diff.length时,说明是对nums[i]及以后的整个数组都进行修改,那么就不需要再给diff数组减val了。

解释题目:
给你输入一个长度为n的数组nums,其中所有元素都是 0。再给你输入一个bookings,里面是若干三元组(i,j,k),每个三元组的含义就是要求你给nums数组的闭区间[i-1,j-1]中所有元素都加上k。请你返回最后的nums数组是多少?

PS:因为题目说的n是从 1 开始计数的,而数组索引从 0 开始,所以对于输入的三元组(i,j,k),数组区间应该对应[i-1,j-1]。

class Solution {
    
    
    public int[] corpFlightBookings(int[][] bookings, int n) {
    
    
        // nums 初始化为全 0
        int[] nums = new int[n];
        // 构造差分解法
        Difference df = new Difference(nums);

        for (int[] booking : bookings) {
    
    
            // 注意转成数组索引要减一哦
            int i = booking[0] - 1;
            int j = booking[1] - 1;
            int val = booking[2];
            // 对区间 nums[i..j] 增加 val
            df.increment(i, j, val);
        }
        // 返回最终的结果数组
        return df.result();
    }
}

class Difference {
    
    
    // 差分数组
    private int[] diff;

    public Difference(int[] nums) {
    
    
        diff = new int[nums.length];
        // 构造差分数组
        diff[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
    
    
            diff[i] = nums[i] - nums[i - 1];
        }
    }

    /* 给闭区间 [i,j] 增加 val(可以是负数)*/
    public void increment(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;
    }
}

猜你喜欢

转载自blog.csdn.net/u012124438/article/details/113762176