1109-航班预订统计

题目

1109. 航班预订统计

难度中等 236

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

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

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

示例 1:

输入: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]

示例 2:

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

提示:

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

思路

  • 暴力

    时间复杂度为O(N^2^)。

  • 观察实例:

    航班编号 1 2 3 4 5
    预订记录 1 : 10 10
    预订记录 2 : 20 20
    预订记录 3 : 25 25 25 25
    总座位数: 10 55 45 25 25

    如果是对于bookings或者n分别进行嵌套循环的话,复杂度也是O(N^2^),不可接受。因此思考O(N)的方法。

    对于firsti ,lasti ,可以发现每个seati都要加载firsti的位置,之后复制就可以了,在lasti之后的位置减去seati。因此可以先对数组进行遍历使得结果数组res在每个first出现的位置都加上seat,在每个last的后一个位置减去seat。最后进行前缀累加即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
vector<int> res(n+1,0);
for(int i=0;i<bookings.size();++i){
res[bookings[i][0]-1] += bookings[i][2];
res[bookings[i][1]] -= bookings[i][2];
}
for(int j=1;j<n;j++){
res[j] += res[j-1];
}
res.resize(n);
return res;
}
};

1588-所有奇数长度子数组的和

题目

给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。

子数组 定义为原数组中的一个连续子序列。

请你返回 arr 中 所有奇数长度子数组的和 。

示例 1:

输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58

示例 2:

输入:arr = [1,2]
输出:3
解释:总共只有 2 个长度为奇数的子数组,[1] 和 [2]。它们的和为 3 。

示例 3:

输入:arr = [10,11,12]
输出:66

提示:

1 <= arr.length <= 100
1 <= arr[i] <= 1000

思路

  • 暴力

  • 统计次数,运用乘法

    对于arr[i] ,在包含arr[i]的前提下,其左侧有i+1个数字,右侧有arr.size()-i个数字。

    如果左边分别取0、2、4、8……等偶数个临近数字作为一组,右边则也应该取偶数长度的数字作为一组,这样合并后正好是奇数个长度。因此arr[i]在这种条件下会加(i+1+1)/2*(arr.size()-i+1)/2次。这个公式可以通过带入几个数字找到规律。

    如果左边分别取1、3、5、7……等奇数个临近数字作为一组,右边也应该取奇数长度的数字作为一组,这样合并吼正好是奇数个长度。因此arr[i]在这种条件下会加(i+1)/2*(arr.size()-i)/2次。这个公式可以通过带入几个数字找到规律。

    解释下(i+1+1)/2*(arr.size()-i+1)/2

    • 对于i为奇数的情况:左边可以有0、2、4……i+1总共(i+2)/2个情况。
    • 对于i为偶数的情况:左边可以有0、2、4……i个总共i/2+1个。

    以上可以统一为(i+2)/2

    奇数同理。

代码

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int s = 0;
for(int i=0;i<arr.size();i++){
int leftOdd = (i+2)/2,leftEven = (i+1)/2;
int rightOdd = (arr.size()-i+1)/2,rightEven=(arr.size()-i)/2;
s+=(leftOdd*rightOdd+leftEven*rightEven)*arr[i];
}
return s;
}
};