从Leetcode120思考满映射的处理方法

思考一些小事情

Posted by Snorlaxa on 2021-08-10

三角形最小路径和

Leetcode120 三角形最小路径和

给定一个三角形 triangle ,找出自顶向下的最小路径和。

每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。

示例 1:

输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
输出:11
解释:如下面简图所示:
2
3 4
6 5 7
4 1 8 3
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)

自顶向下还是自底向上

每一层的最短路径依赖于上一层的最短路径,如[i,j]位置的最短路径依赖于上一层[i-1,j]和[i-1,j+1]两个位置的最短路径。这种重复利用结果,并且可以找出
一定规律的问题,优先使用动态规划解决。

思考dp的定义:

很自然地想到用dp[i,j]表示从第0层到第i层第j个元素的最短路径和,这个值将用于下一层每个元素的最短路径和的计算。这是一种自上而下的方式,计算完第i层后才会去计算第i+1层。但这种方式需要考虑很多边界问题,如i=0和i=1需要特殊讨论,j=0和j在末尾也需要特殊讨论。并且在计算出结果后,还需要统计最后一层中最小的那个值,需要额外的一次遍历。

在计算i+1层时使用i层的结果,必然会产生边界问题,因为j=0和j=n-1两种情况的处理方法与中间的数据不同。
这种方式会求出从i层到i+1层的一系列可行路径,而计算同样的路径,如果在计算i层时使用i+1层的值,j=0、j=n-1与其他数据的计算方式并无两样,就不会产生边界问题。这样不断向上计算还能够自动把结果汇总到第0层,无需遍历结果求最小值。

满映射

更深层次地去讨论一个问题:为什么从i层计算i+1层的路径,和从i+1层计算i层的路径相差这么大?

这两层的区别在于i层的元素数量比i+1层小,从i层到i+1层的路径相当于从一个小的集合映射到大的集合。如果这个小的集合到大的集合是满映射,我们遍历小的集合时,遍历到的每一个元素都存在着一个映射关系;而如果遍历大的集合则会遍历到无映射关系的元素,就需要做一些额外的判断和讨论。即便没有满映射的关系,遍历小集合也比大集合有更大的概率避免边界问题。

在这个问题中,i层到i+1层可以视作从i集合到i+1集合的满映射,i层的元素集合的所有元素必然在i+1层集合中有映射的元素,所以当我们遍历i层元素的时候,
每一个元素都有从i到i+1的最短路径。

总结

这个问题带来的意义是,当我们面对存在满映射关系的两个集合,并且要遍历映射关系时,选择小集合来遍历可以避免很多边界问题。