写在前面
最近想复习一下算法与数据结构的知识,正好准备看看MIT的算法导论这门课。
第一节课讲述一个问题 peak finding
主要内容
问题1: 在一个一维的数组当中找到一个极大值,这个极大值的定义就是大于等于两边元素的值就是极大值,两端的值只要大于其有值的那一边的元素就算是极大值。
这算是一个抛砖引玉的题目,最简单额思路就是遍历整个数组,一个元素一个元素的检查是否满足。时间复杂度为o(n)。
优化解也比较容易想到:采用分治的思想。取数组中间那个元素判断是否是极大值点,如果不是,将搜索范围减小至大于该值的一半区间(如果两边的元素都大于这个元素就随便取一个)。再对选取的区间做以上相同的操作直到找到解为止。
因为这样的好处就是直接可以判定所选取的区间里肯定有极大值,至于另一半有没有我不需要知道也没必要判定。
这样整体的时间复杂度将降低到o(logn)。
问题2:2维矩阵求Peak。这时候的定义就是该元素的值如果大于等于其上下左右的元素的值就是peak.
这道题目是上一题的一个递进,如果使用最暴力额解法是遍历所有的元素判断是否合适,时间复杂度将为o(n*m)。
按照第一题的思路我们可以得到如下启发,我们只需要判断哪里必然有极大值将区域缩小,不用遍历所有的区域也能找到极大值点。如果将矩阵的每个元素看成高,行和列的下标看成平面的x和y轴座标那么该矩阵可以构成一个三维点阵。可以知道的是矩阵的四条边界都是最小的地方,中间任意一个点的值都比外部边界大。这样我们只需要找到一个点和其四周的边界保证这个点比包围这个区域的四条边界上的数值大就一定能保证这块区域里存在极大值点。
怎么找这个点呢?
首先我们找到矩阵的最中间那一列找到这一列的最大值。判断其是否是极大值点,如果不是那么一定是其左右点至少有一点比他的值大。我们选择比该值大的那个点(如果都满足随便选哪一个都可以)。整个矩阵被分成了两部分,我们选取的这个点所在的那部分的四条边必然都小于这个点的值,因为分隔两部分的列所在的那条边的最大值都小于这个值那么那条边必然页小于这个点的值,这样这块区域必然含有极大值,这样问题的规模就被缩小了一半,我们对这块区域继续做相同的判断直到找到极大值点。
总体的时间复杂度为o(nlogm)。