LeetCode 题解工作台
3n 块披萨
给你一个披萨,它由 3n 块不同大小的部分组成,现在你和你的朋友们需要按照如下规则来分披萨: 你挑选 任意 一块披萨。 Alice 将会挑选你所选择的披萨逆时针方向的下一块披萨。 Bob 将会挑选你所选择的披萨顺时针方向的下一块披萨。 重复上述过程直到没有披萨剩下。 每一块披萨的大小按顺时针方向由循…
4
题型
5
代码语言
3
相关题
当前训练重点
困难 · 状态·转移·动态规划
答案摘要
我们可以将这个问题转化为:在一个长度为 的环形数组中,选择其中 个不相邻的数,使得这 个数的和最大。 证明如下:
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你一个披萨,它由 3n 块不同大小的部分组成,现在你和你的朋友们需要按照如下规则来分披萨:
- 你挑选 任意 一块披萨。
- Alice 将会挑选你所选择的披萨逆时针方向的下一块披萨。
- Bob 将会挑选你所选择的披萨顺时针方向的下一块披萨。
- 重复上述过程直到没有披萨剩下。
每一块披萨的大小按顺时针方向由循环数组 slices 表示。
请你返回你可以获得的披萨大小总和的最大值。
示例 1:

输入:slices = [1,2,3,4,5,6] 输出:10 解释:选择大小为 4 的披萨,Alice 和 Bob 分别挑选大小为 3 和 5 的披萨。然后你选择大小为 6 的披萨,Alice 和 Bob 分别挑选大小为 2 和 1 的披萨。你获得的披萨总大小为 4 + 6 = 10 。
示例 2:

输入:slices = [8,9,8,6,1,1] 输出:16 解释:两轮都选大小为 8 的披萨。如果你选择大小为 9 的披萨,你的朋友们就会选择大小为 8 的披萨,这种情况下你的总和不是最大的。
提示:
1 <= slices.length <= 500slices.length % 3 == 01 <= slices[i] <= 1000
解题思路
方法一:动态规划
我们可以将这个问题转化为:在一个长度为 的环形数组中,选择其中 个不相邻的数,使得这 个数的和最大。
证明如下:
- 当 时,我们可以选择数组中的任意一个数。
- 当 时,那么一定存在一个数,使得它的某一侧有两个连续的数没有被选择,而另一侧至少有一个数没有被选择。因此,我们可以将这个数和它两侧的数一起从数组中删除,然后剩下的 个数构成一个新的环形数组。问题规模缩小成了在长度为 的环形数组中选择 个不相邻的数,使得这 个数的和最大。
因此,我们需要求解的问题可以转化为:在一个长度为 的环形数组中,选择其中 个不相邻的数,使得这 个数的和最大。
环形数组中,如果选择了第一个数,那么最后一个数就不能选择,如果选择了最后一个数,那么第一个数就不能选择,因此我们可以将环形数组拆成两个数组,一个是去掉第一个数的,一个是去掉最后一个数的,然后分别求解这两个数组的最大值,最后取两个最大值中的较大值即可。
我们用一个函数 ,表示在数组 中选择 个不相邻的数,使得这 个数的和最大,那么我们的目标就是求 和 中的较大值。
函数 的求解方法如下:
我们记数组 的长度为 ,定义 表示在数组 的前 个数中选择 个不相邻的数的最大和。
考虑 ,如果我们不选择第 个数,那么 ,如果我们选择第 个数,那么 ,因此我们可以得到状态转移方程:
最后返回 即可。
时间复杂度 ,空间复杂度 。其中 是数组 的长度。
class Solution:
def maxSizeSlices(self, slices: List[int]) -> int:
def g(nums: List[int]) -> int:
m = len(nums)
f = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
f[i][j] = max(
f[i - 1][j], (f[i - 2][j - 1] if i >= 2 else 0) + nums[i - 1]
)
return f[m][n]
n = len(slices) // 3
a, b = g(slices[:-1]), g(slices[1:])
return max(a, b)
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | complexity is O(n^2) due to iterating over slices and possible picks in DP. Space complexity is O(n^2) for the DP table, reducible to O(n) using optimized rolling array techniques. |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Checking if you recognize the circular array pattern.
- question_mark
Expecting you to translate circular dependency into two linear DP scenarios.
- question_mark
Observing understanding of state transitions for dynamic programming.
常见陷阱
外企场景- error
Attempting a purely greedy solution without considering adjacent slice removal.
- error
Ignoring the circular array edge cases when picking the first or last slice.
- error
Incorrect DP indexing that does not account for skipping one slice after picking.
进阶变体
外企场景- arrow_right_alt
Select maximum sum from a linear array where picking one element removes its neighbors.
- arrow_right_alt
Maximizing non-adjacent selections from a 2n-length array with fixed number of picks.
- arrow_right_alt
Generalized k-consecutive removal problem in a circular array.