问题描述
小M在整理桌子上的装饰品时,发现高度差异过大的装饰品放在一起会显得不美观。她希望通过交换装饰品的位置,使得它们的高度变化更加平滑,从而最小化整体的丑陋值。装饰品的丑陋值定义为相邻装饰品高度差的绝对值之和。小M可以任意交换装饰品的位置,目标是找到一种装饰顺序,使得丑陋值达到最小。
例如:当三个装饰品的高度分别为 3, 1, 2 时,通过交换它们的顺序,可以将高度排列为 1, 2, 3,此时丑陋值为 |1-2| + |2-3| = 2,这是最优解。
测试样例
样例1:
输入:
n = 3, a = [3, 1, 2]
输出:2
样例2:
输入:
n = 5, a = [10, 20, 30, 5, 15]
输出:25
样例3:
输入:
n = 4, a = [100, 200, 50, 150]
输出:150
问题解析
要解决这个问题,我们需要找到一种排列方式,使得相邻装饰品的高度差的绝对值之和最小。这里求解最小的丑陋值,实际上就是求解相邻数值间最小距离和。绘制数轴即可发现,顺序排列的距离和一定是最小距离和。
故而,只需将储存在列表a中的高度进行顺序排列,再根据丑陋值的定义,计算相邻数字间差值,即可求得最小丑陋值。
def solution(n: int, a: list) -> int:
lis = sorted(a) #按高度对装饰品进行顺序排列
ugly = 0 #丑陋值
#计算丑陋值之和
for i in range(len(a) - 1):
ugly += lis[i + 1] - lis[i]
return ugly
此时代码运行后,测试样例输出均正确,再对代码进行进一步优化。
同样是利用数轴,任意选取n个数字按照顺序排列在数轴上,不难得出其相邻数字距离之和即为最小值和最大值的距离,也就是最小值与最大值之差。
则此时代码可优化为
def solution(n: int, a: list) -> int:
#将装饰品按高度进行顺序排列
left = min(a) #装饰品最小高度
right = max(a) #装饰品最大高度
return right - left
同样测试正确。
总结
总的来说,这道问题并不复杂,在未看破其背后隐藏的数学规律前,也可以采用贪心算法来求解,但当我们运用可视化——利用数轴来总结规律时,就可以很好地避免掉相对复杂的处理方式,降低时间复杂度,直接发现问题规律来处理数据。