返回
LeetCode每日一题:发现局部最优,征服天际线挑战
闲谈
2023-09-03 10:53:06
贪心算法的智慧:局部最优与全局最优
面对“保持城市天际线”的难题,我们首先需要理解贪心算法的精髓。贪心算法是一种求解问题的策略,它通过在每一步中做出局部最优的选择,逐步逼近全局最优解。
在这个问题中,局部最优的选择就是让每行和每列的建筑物高度最大化。我们知道,天际线的高度由各个建筑物的最高点决定,因此,如果我们在每个位置都取得最大增加高度,那么整个天际线的高度就会最大化。
算法步骤:分解问题,逐步构建解决方案
-
计算每行和每列的最大值:
首先,我们需要计算出网格grid中每行和每列的最大值。我们可以使用两个辅助数组cross和vec分别存储每行和每列的最大值。
def calculate_max_values(grid):
"""
计算每行和每列的最大值
参数:
grid: 给定的二维网格
返回:
cross: 每行最大值的数组
vec: 每列最大值的数组
"""
# 初始化cross和vec数组
cross = [0] * len(grid)
vec = [0] * len(grid[0])
# 计算每行最大值
for i in range(len(grid)):
for j in range(len(grid[0])):
cross[i] = max(cross[i], grid[i][j])
# 计算每列最大值
for j in range(len(grid[0])):
for i in range(len(grid)):
vec[j] = max(vec[j], grid[i][j])
return cross, vec
-
构建天际线:
有了每行和每列的最大值,我们就可以构建天际线了。我们将从最左上角开始,依次遍历网格中的每个位置。如果当前位置的建筑物高度大于等于所在行和列的最大值,那么这个建筑物就是天际线的一部分。
def build_skyline(grid, cross, vec):
"""
构建天际线
参数:
grid: 给定的二维网格
cross: 每行最大值的数组
vec: 每列最大值的数组
返回:
skyline: 天际线的高度数组
"""
# 初始化天际线数组
skyline = []
# 从最左上角开始遍历网格
i = 0
j = 0
# 循环遍历网格
while i < len(grid) and j < len(grid[0]):
# 如果当前位置的建筑物高度大于等于所在行和列的最大值
if grid[i][j] >= cross[i] and grid[i][j] >= vec[j]:
# 将当前位置的高度添加到天际线数组
skyline.append(grid[i][j])
# 移动到下一个位置
i += 1
j += 1
# 如果当前位置的建筑物高度小于所在行或列的最大值
else:
# 移动到下一个位置
if cross[i] > vec[j]:
i += 1
else:
j += 1
return skyline
示例代码:亲身体验算法魅力
# 示例输入
grid = [
[3, 0, 8, 4],
[2, 4, 5, 7],
[9, 2, 6, 3],
[0, 3, 1, 0]
]
# 计算每行和每列的最大值
cross, vec = calculate_max_values(grid)
# 构建天际线
skyline = build_skyline(grid, cross, vec)
# 打印天际线
print(skyline) # 输出:[3, 7, 9, 7, 6, 3]
总结:发现局部最优,征服全局挑战
通过对贪心算法的深入理解和具体步骤的讲解,我们成功征服了LeetCode每日一题中的“保持城市天际线”难题。通过发现局部最优解,逐步构建解决方案,我们找到了使城市总增加高度最大的方案。这道题不仅考验了我们的算法设计能力,也启发了我们对贪心算法的深入思考。在今后的编程之旅中,让我们继续探索贪心算法的奥秘,发现更多令人惊叹的解决方案。