ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Peak Finding

2020-08-31 09:03:15  阅读:429  来源: 互联网

标签:return column len middle Peak Finding peak row


问题描述

一维的情形为例,Peak Finding 描述这样一个问题。

给定一个数组 a,是否能够找到这样一个坐标 i,使得 \(a[i - 1] \le a[i] \le a[i + 1]\),这样的坐标 i 被称为 peak

特别地,在边界上的元素只需要保证大于等于与其相邻的一个元素,也被判定为 peak


Straightforward Algorithm

遍历数组,找到是否存在一个位置上的元素,该元素大于等于与其所有的相邻元素。

复杂度 \(\Theta(N)\)。

def peak_finding(a):
    if len(a) == 0:
        return None
    if len(a) == 1 or a[0] >= a[1]:
        return 0
    if a[-1] >= a[-2]:
        return len(a) + 1
    for i in range(1, len(a) - 1):
        left = a[i - 1]
        right = a[i + 1]
        if left <= a[i] <= right:
            return i

Divide and Conquer

分而治之算法。考察 \(a[n / 2]\) 及与其相邻的元素。

  • 如果 \(a[n / 2]\) 小于其邻居,则可以在左侧的子数组中递归寻找 peak
  • 如果 \(a[n / 2]\) 小于其邻居,则可以在右侧的子数组中递归寻找 peak
  • 如果以上两种情形均不成立,则 \(n / 2\) 就是一个 peak
def peak_finding(a):
    if len(a) == 0:
        return None
    return divide_and_conquer(a, 0, len(a) - 1)

def divide_and_conquer(a, low, high):
    if low >= high:
        return low
    middle = (low + high) // 2
    if a[middle - 1] > a[middle]:
        return divide_and_conquer(a, low, middle - 1)
    elif a[middle + 1] > a[middle]:
        return divide_and_conquer(a, middle + 1, high)
    else:
        return middle

假设 \(T(N)\) 是该算法运行的时间,则有

\[T(N) = T(N / 2) + \Theta(1) = \underbrace{\Theta(1) + \dots + \Theta(1)}_{log(N)} = \Theta(logN) \]


问题扩展

问题扩展至二维情形。如上图,当且仅当

\[a \ge x, x \in \{b, c, d, e\} \]

成立时,\(a\) 所在的位置称为 peak

尝试找出二维情形下的一个 peak


Greedy Ascent Algorithm

从数组的任意位置开始,向数组元素增大的方向移动,直至周围的数组元素均小于当前元素。

复杂度 \(\Theta(MN)\)。

def peak_finding(a):
    if len(a) == 0 or len(a[0]) == 0:
        return None
    if len(a) == 1 or len(a[0]) == 1:
        return (0, 0)
    n = len(a)
    m = len(a[0])
    location = (n // 2, m // 2)
    while True:
        row, column = location
        value = a[row][column]
        if row > 0 and a[row - 1][column] > value:
            location = (row - 1, column)
            continue
        if row < n - 1 and a[row + 1][column] > value:
            location = (row + 1, column)
            continue
        if column > 0 and a[row][column - 1] > value:
            location = (row, column - 1)
            continue
        if column < m - 1 and a[row][column + 1] > value:
            location = (row, column + 1)
            continue
        return location

Divide and Conquer

分而治之算法。考察第 \(j = m / 2\) 列。

  • 找出这一列上最大的元素 \(a[i][j]\),将其与其左右相邻的元素比较
  • 如果 \(a[i][j - 1] > a[i][j]\),则可以在左侧的列中递归寻找二维 peak
  • 如果 \(a[i][j + 1] > a[i][j]\),则可以在右侧的列中递归寻找二维 peak
  • 如果以上两种情形均不成立,则 \((i, j)\) 就是一个二维 peak
def peak_finding(a):
    if len(a) == 0 or len(a[0]) == 0:
        return None
    m = len(a[0])
    return divide_and_conquer(a, 0, m - 1)

def divide_and_conquer(a, low, high):
    if low >= high:
        row_index = find_max_row_on_column(a, low)
        return row_index, low
    middle = (low + high) // 2
    row_index = find_max_row_on_column(a, middle)
    if a[row_index][middle - 1] > a[row_index][middle]:
        return divide_and_conquer(a, low, middle - 1)
    elif a[row_index][middle + 1] > a[row_index][middle]:
        return divide_and_conquer(a, middle + 1, high)
    else:
        return row_index, middle

def find_max_row_on_column(a, column):
    max_row = 0
    for i in range(len(a)):
        if a[i][column] > a[max_row][column]:
            max_row = i
    return max_row

假设 \(T(N, M)\) 是该算法运行的时间,则有

\[T(N, M) = T(N, M / 2) + \Theta(N) = \underbrace{\Theta(N) + \dots + \Theta(N)}_{log(M)} = \Theta(NlogM) \]

标签:return,column,len,middle,Peak,Finding,peak,row
来源: https://www.cnblogs.com/stO-Orz/p/13587748.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有