这里写自定义目录标题
更多精彩内容
这里是带你游历编程世界的Dashcoding编程社,我是Dash/北航硕士/ICPC区域赛全国排名30+/给你呈现我们眼中的世界!
256题算法特训课,帮你斩获大厂60W年薪offer
原题
米哈游校招真题房屋
B站动画详解
问题分析
题目要求我们找到满足相邻房屋高度之和等于给定数组 b b b 的所有可能高度组合。为了实现这个目标,首先我们需要分析房屋高度的变化规律。假设第一个房屋的高度为 a 1 a_1 a1,那么可以通过 b 1 = a 1 + a 2 b_1 = a_1 + a_2 b1=a1+a2 得到第二个房屋的高度 a 2 a_2 a2。接着通过 b 2 = a 2 + a 3 b_2 = a_2 + a_3 b2=a2+a3 计算第三个房屋的高度,依次类推。需要注意的是,在这过程中,高度之间存在依赖关系,计算 a i + 1 a_{i+1} ai+1 时依赖于之前的高度 a i a_i ai。为了确保高度符合正整数要求,且解的数量为最大化,我们要分析在什么情况下有解。该题目实际上转化为在限定范围内寻找符合条件的整数解,因此我们需要对高度进行上下界约束。
思路分析
使用数学思维来解决这个问题,我们可以通过一次遍历计算出每一个房屋可能的高度区间。假设 s s s 表示当前累积的高度总和,根据奇偶性,我们分别对区间进行调整。对于奇数位置的高度,我们累加 b i b_i bi,并更新当前可能的最大高度;对于偶数位置,我们累减 b i b_i bi,并更新最小高度。最终通过分析得到的最小和最大值的差异,我们可以计算出符合条件的解的数量。具体来说,结果为 r − l − 1 r - l - 1 r−l−1,其中 r r r 和 l l l 分别是最大和最小的累积值。需要注意的是,当结果为负数时,解的数量为零。
算法实现
下面的代码实现了上述算法逻辑。首先通过输入读取房屋数量 n n n 和数组 b b b。然后通过一次循环遍历数组 b b b,根据当前索引的奇偶性对累积和 s s s 进行调整,并更新上下界 r r r 和 l l l。在遍历完成后,计算结果为 m a x ( 0 , r − l − 1 ) max(0, r - l - 1) max(0,r−l−1),确保解的数量为非负值。代码使用了 long long 类型来处理可能的大数运算,确保在大输入规模下仍然能够正确计算。
代码详解
标准代码程序
C++代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n = 0;
cin >> n;
ll r = LLONG_MAX, l = 0;
ll s = 0;
for(int i = 1; i < n; ++i) {
int b = 0;
cin >> b;
if(i % 2 == 1) {
s += b;
r = min(r, s);
}
else {
s -= b;
l = max(l, s);
}
}
ll ans = max(0ll, r - l - 1);
cout << ans;
return 0;
}
Java代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long r = Long.MAX_VALUE, l = 0;
long s = 0;
for (int i = 1; i < n; ++i) {
int b = sc.nextInt();
if (i % 2 == 1) {
s += b;
r = Math.min(r, s);
} else {
s -= b;
l = Math.max(l, s);
}
}
long ans = Math.max(0, r - l - 1);
System.out.println(ans);
}
}
Python代码
def main():
n = int(input())
r, l = float('inf'), 0
s = 0
for i in range(1, n):
b = int(input())
if i % 2 == 1:
s += b
r = min(r, s)
else:
s -= b
l = max(l, s)
ans = max(0, r - l - 1)
print(ans)
if __name__ == "__main__":
main()
Javascript代码
function main() {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('', (n) => {
let r = Number.MAX_SAFE_INTEGER, l = 0;
let s = 0;
const bArr = [];
rl.on('line', (line) => {
bArr.push(...line.split(' ').map(Number));
for (let i = 1; i < n; i++) {
let b = bArr[i - 1];
if (i % 2 === 1) {
s += b;
r = Math.min(r, s);
} else {
s -= b;
l = Math.max(l, s);
}
}
const ans = Math.max(0, r - l - 1);
console.log(ans);
rl.close();
});
});
}
main();
复杂度分析
时间复杂度
在这个问题中,算法主要依赖于对数组 b b b 的一次线性遍历。考虑到 n n n 表示房屋数量,而输入的数组 b b b 有 n − 1 n-1 n−1 个元素,因此遍历的时间复杂度为 O ( n ) O(n) O(n)。在每次遍历中,我们进行常数次的加法、减法、取最小值和取最大值操作,这些操作的时间复杂度都是 O ( 1 ) O(1) O(1)。因此,整体的时间复杂度为 O ( n ) O(n) O(n)。
空间复杂度
从空间复杂度的角度来看,算法只使用了几个辅助变量来存储当前的累积和 s s s、上下界 r r r 和 l l l,以及输入的整数 b b b。这些变量的空间占用是常数级别的,因此空间复杂度为 O ( 1 ) O(1) O(1)。即使输入规模达到最大值( n ≤ 1 0 5 n \leq 10^5 n≤105),算法也只需要额外的常量空间,因此在空间利用上是非常高效的。
总结
这道题目通过对数学思维的巧妙应用,成功将问题转化为区间上下界的求解问题。通过一次线性遍历,我们能够有效地计算出所有可能的房屋高度组合数量。关键在于根据累积和的奇偶性对上下界进行动态调整,最终通过结果公式 r − l − 1 r - l - 1 r−l−1 计算出满足条件的解的数量。由于时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1),该算法能够在大规模数据下高效运行,非常适合处理上限为 1 0 5 10^5 105 的问题规模。这种通过分析区间并推导数学关系的思路,在处理类似问题时具有广泛的应用潜力。