经典算法精讲之平滑处理
人口分布图的模糊平滑处理
在城市规划和数据分析中,常常需要对人口分布数据进行平滑处理,以消除异常波动,更清晰地呈现整体趋势。现有一份城市人口分布图,使用一个二维列表 city_map 表示,其中 city_map[i][j] 为第 i 行第 j 列区域的人口数量(整数)。
请你实现一个设计一个来函数其功能如下:
模糊处理:对于城市中的每一个区域(即每个格子),用其自身及周围所有相邻区域(共8个,包括上下左右和四个对角线)的人口数平均值(向下取整)来替换该区域的人口数。
边界处理:对于边缘和角落上的区域,只考虑实际存在的相邻区域(不会越界)。
返回新分布图:函数返回一个新的二维列表,表示模糊处理后的人口分布,不修改原始输入。
city_map = [
[5, 12, 25, 9],
[18, 30, 22, 15],
[27, 21, 13, 8],
[10, 14, 16, 20]
]
解法分析
def smooth_population(city_map):
“””
对城市区域人口进行模糊平滑处理。
每个区域用自身和周围八格的平均人口数(向下取整)替换。
“””
rows = len(city_map)
cols = len(city_map[0])
result = [[0 for _ in range(cols)] for _ in range(rows)]
for x in range(rows):
for y in range(cols):
pop_sum = count = 0
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
nx, ny = x + dx, y + dy
if 0 <= nx < rows and 0 <= ny < cols:
pop_sum += city_map[nx][ny]
count += 1
result[x][y] = pop_sum // count
return result
步骤分解
- 明确目标
我们希望让每一个区域(格子)的人口数据,变得更平滑。实现方法是:用它本身和周围八个格子的平均人口数来替换当前的人口数。这样可以消除偶然的高峰或低谷,使整体人口分布趋势更清晰。 构建输出矩阵
rows = len(city_map) cols = len(city_map[0]) result = [[0 for _ in range(cols)] for _ in range(rows)]
• rows和cols分别表示人口分布图的行数和列数。
• result用于存储模糊处理后的新人口分布,初始值全部为0。- 遍历原矩阵的每一个格子
我们用双重循环,依次考察每一个区域。for x in range(rows): for y in range(cols):
- 对每一个格子,统计邻域人口总和和格子数
pop_sum = count = 0 for dx in [-1, 0, 1]: for dy in [-1, 0, 1]: nx, ny = x + dx, y + dy if 0 <= nx < rows and 0 <= ny < cols: pop_sum += city_map[nx][ny] count += 1
• 这里dx和dy的组合会覆盖当前格子的上、下、左、右和四个对角线,再加上自身。
• nx, ny表示邻居的实际坐标。
• 通过if 0 <= nx < rows and 0 <= ny < cols来确保不越界,只统计实际存在的邻居。
• pop_sum累计人口总数,count累计实际统计的格子数
计算平均数(向下取整)并更新结果
result[x][y] = pop_sum // count
用整数除法//得到人口平均值,并填到新表格的对应位置。返回新的人口分布表
return result
算法要点:
这种“平滑”处理方法广泛应用于图像模糊、地形平滑、噪声去除等领域,其本质是用邻域(周围格子)
的平均值来代替原始数值,从而消除局部异常和突出变化。
边界处理是实际编程中非常重要的细节。我们在计算时需要确保不会越界访问数据,保证算法的健壮性和正确性。
本算法的时间复杂度为 O(N×M),即与输入表格的格子数成正比。每个格子的处理都是常数时间,
适合处理较大规模的数据。
补充思考:
如果希望模糊效果更强或边界更加平滑,可以考虑扩大邻域范围(比如使用 5x5 或更大的窗口)。
可以尝试使用加权平均,让不同邻居对结果的影响权重不同(如中心格子权重大,周边权重小),实现更加灵活和真实的平滑效果。
该方法不仅限于人口分布,还可以推广到许多类似的二维数据平滑场景,例如图像处理、地理信息数据分析和气象数据处理等。