LeetCode 799. 香槟塔
题目描述
将玻璃杯摆成金字塔形状,第1层1个杯子,第2层2个,......,第100层100个。
每个杯子容量为1杯香槟。从顶层倒入poured杯香槟,当杯子满时(量≥1),多余香槟等量流入下一层左右两个杯子。
给定poured、query_row和query_glass,返回第query_row行第query_glass个杯子的香槟量(范围[0,1])。
思路一:二维数组逐层模拟
算法思想
- 用二维数组
tower[i][j]表示第i行第j个杯子的香槟量(初始为0)。 - 将
poured倒入顶层:tower[0][0] = poured。 - 从第0行逐行处理到第99行:
- 若
tower[i][j] > 1,计算溢出量over = tower[i][j] - 1,平分到tower[i+1][j]和tower[i+1][j+1],并设置tower[i][j] = 1。 - 若某行无溢出,提前终止。
- 若
- 返回
min(1.0, tower[query_row][query_glass])。
代码实现(C++)
cpp
class Solution {
public:
double champagneTower(int poured, int query_row, int query_glass) {
double tower[101][101] = {0.0};
tower[0][0] = poured;
for (int i = 0; i < 100; ++i) {
bool hasOverflow = false;
for (int j = 0; j <= i; ++j) {
if (tower[i][j] > 1.0) {
double over = tower[i][j] - 1.0;
tower[i+1][j] += over / 2.0;
tower[i+1][j+1] += over / 2.0;
tower[i][j] = 1.0;
hasOverflow = true;
}
}
if (!hasOverflow) break;
}
return min(1.0, tower[query_row][query_glass]);
}
};
复杂度分析
- 时间复杂度:O(1)(常数级)。
- 空间复杂度:O(1)(101×101数组)。
思路二:一维滚动数组(空间优化)
算法思想
- 使用两个一维数组
cur和next:cur表示当前层,初始cur[0] = poured。- 处理到第
query_row - 1行:- 清空
next。 - 若
cur[j] > 1.0,溢出量over平分到next[j]和next[j+1]。 - 交换
cur和next进入下一层。
- 清空
- 返回
min(1.0, cur[query_glass])。
代码实现(C++)
cpp
class Solution {
public:
double champagneTower(int poured, int query_row, int query_glass) {
vector<double> cur(101, 0.0), next(101, 0.0);
cur[0] = poured;
for (int i = 0; i < query_row; ++i) {
fill(next.begin(), next.end(), 0.0);
for (int j = 0; j <= i; ++j) {
if (cur[j] > 1.0) {
double over = cur[j] - 1.0;
next[j] += over / 2.0;
next[j+1] += over / 2.0;
}
}
swap(cur, next);
}
return min(1.0, cur[query_glass]);
}
};
复杂度分析
- 时间复杂度:O(1)(常数级)。
- 空间复杂度:O(1)(两个长度101的数组)。
总结
- 二维数组法直观,适合理解;一维滚动数组法空间更优。
- 两种方法均需用
min(1.0, ...)确保结果不超过杯子容量。