Peak Finding
来源:互联网 发布:手机fps帧数显示软件 编辑:程序博客网 时间:2024/04/30 04:14
1D Peak Finding
Objective
Given an array A with n elements, find the index i of the peak element A[i] where A[i] >= A[i - 1]
and A[i] >= A[i + 1]. For elements on the boundaries of the array, the element only needs to be greater than or equal to its lone neighbor to be considered a peak. Or, say A[-1] = A[n] =
Algorithm
- Take the middle element fo A, A[
n2 ], and compare that element to its neighbors - If the middle element is greater than or equal to its neighbors, then by definition, that element is a peak. Reture its index
n2 - Else, if the element to the left is greater than the middle element, then recurse and use this algorithm on the left half of the array, not including the middle element.
- Else, the element to the right must be greater than the middle element. Recurse and use this algorithm on the right half of the array, not including the middle element.
Runtime Analysis
T(n) = T(
T(n) = T(
T(n) = T(
T(n) = T(
Substitute k =
T(n) = T(
= T(1) + c
= O(log n)
L = [4, 8, 5, 6, 9, 10, 13, 4, 5 ,6, 0]print L[len(L) / 2:]print L[: len(L) / 2]print len(L) / 2L[len(L) / 2]
def peakFindStraight(L): ''' Find a peak in a straight way Runtime: O(len(L)) ''' if len(L) == 0: return None if len(L) == 1: return 0 for i in xrange(len(L)): if i == 0: if L[i] >= L[i + 1]: return i elif i == len(L) - 1: if L[i] >= L[i - 1]: return i else: if L[i] >= L[i + 1] and L[i] >= L[i - 1]: return i
print peakFindStraight(L)
def peakFinding(L, low, high): ''' Peak finding recursive way. It is similar to binary search. Runtime: O(log(len(L))) ''' mid = low + (high - low) / 2 if mid == 0 or mid == len(L) - 1 or (L[mid] >= L[mid - 1] and L[mid] >= L[mid + 1]): return mid elif L[mid - 1] > L[mid]: return peakFinding(L, low, mid - 1) else: return peakFinding(L, mid + 1, high)
print Lpeakindex = peakFinding(L, 0, len(L) - 1)print L[peakindex]
2D Peak Finding
Objective
Given an n*n matrix M, find the indices of a peak element M[i][j] where the element is greater
than or equal to its neighbors, M[i + 1][j], M[i - 1][j], M[i][j + 1], and M[i][j - 1]. For elements
on the boundaries of the matrix, the element only needs to be greater than or equal to the neighbors
it has to be considered a peak.
Algorithm 2D:
- Pick middle column j = m / 2
- Find global maximum on column j at (i, j)
- Compare (i, j - 1), (i, j), (i, j + 1)
- Pick left columns of (i, j - 1) > (i, j)
- Similarly for right
- (i, j) is a 2D-peak if neither condition holds <- WHY
- Solve the new problem with half the number of columns.
- When you have a single column, find global maximum and you're done.
The complexity is:
If T(n, m) denotes work required to solve problem with n rows and m columns
T(n, m) = T(n, m/2) +
T(n, m) =
=
problemMatrix = [[ 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2],[ 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3],[ 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4],[ 7, 8, 9, 10, 11, 10, 9, 8, 7, 6, 5],[ 8, 9, 10, 11, 12, 11, 10, 9, 8, 7, 6],[ 7, 8, 9, 10, 11, 10, 9, 8, 7, 6, 5],[ 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4],[ 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3],[ 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2],[ 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1],[ 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0]]
def getDimensions(array): ''' Gets the dimensions for a two-dimensional array Runtime: O(len(array)) ''' rows = len(array) cols = 0 for row in array: if len(row) > cols: cols = len(row) return (rows, cols)
#test getDimensionsgetDimensions(problemMatrix)
class PeakProblem(object): ''' A class representing an instance of a peak-finding problem ''' def __init__(self, array, bounds): ''' A method for initializing an instance of the PeakProblem class. Takes an array and an argument indicating which rows to include. Runtime: O(1) ''' (startRow, startCol, numRow, numCol) = bounds self.array = array self.bounds = bounds self.startRow = startRow self.startCol = startCol self.numRow = numRow self.numCol = numCol def get(self, location): ''' Returns the value of the array at the given location, offset by the coordinates (startRow, startCol). Runtime: O(1) ''' (r, c) = location if not (0 <= r and r < self.numRow): return 0 if not (0 <= c and c < self.numCol): return 0 return self.array[self.startRow + r][self.startCol + c] def getBetterNeighbor(self, location): ''' If (r, c) has a better neighbor, return the neighbor. Otherwise, return the location (r, c) ''' (r, c) = location best = location if r - 1 >= 0 and self.get((r-1, c)) > self.get(best): best = (r - 1, c) if c - 1 >= 0 and self.get((r, c - 1)) > self.get(best): best = (r, c - 1) if r + 1 < self.numRow and self.get((r + 1, c)) > self.get(best): best = (r + 1, c) if c + 1 < self.numCol and self.get((r, c + 1)) > self.get(best): best = (r, c + 1) return best def getMaximum(self, locations): ''' Finds the location in the current problem with the greatest value ''' (bestLoc, bestVal) = (None, 0) for loc in locations: if bestLoc is None or self.get(loc) > bestVal: (bestLoc, bestVal) = (loc, self.get(loc)) return bestLoc def isPeak(self, location): ''' Returns true if the given location is a peak in the current subproblem. ''' return (self.getBetterNeighbor(location) == location) def getSubproblem(self, bounds): ''' Returns a subproblem with the given bounds. The bounds is a quadruple of numbers: (starting row, starting column, # of rows, # of columns). ''' (sRow, sCol, nRow, nCol) = bounds newBounds = (self.startRow + sRow, self.startCol + sCol, nRow, nCol) return PeakProblem(self.array, newBounds) def getSubproblemContaining(self, boundList, location): ''' Returns the subproblem containing the given location. Picks the first of the subproblems in the list which satisfies that constraint, and then constructs the subproblem using getSubproblem(). Runtime: O(len(boundList)) ''' (row, col) = location for (sRow, sCol, nRow, nCol) in boundList: if sRow <= row and row < sRow + nRow: if sCol <= col and col < sCol + nCol: return self.getSubproblem((sRow, sCol, nRow, nCol)) # shouldn't reach here return self def getLocationInSelf(self, problem, location): ''' Remaps the location in the given problem to the same location in the problem that this function is being called from. Runtime: O(1) ''' (row, col) = location newRow = row + problem.startRow - self.startRow newCol = col + problem.startCol - self.startCol return (newRow, newCol) def printPeakProblem(self): ''' Print the two-dimensional array Runtime: O(self.numRow * self.numCol) ''' for i in range(self.startRow, self.numRow): for j in range(self.startCol, self.numCol): print '{:4}'.format(self.get((i, j))), print
def createProblem(array): ''' Constructs an instance of the PeakProblem object for the given array, using bounds derived from the array using the getDimensions function. Runtime: O(len(arry)) ''' (rows, cols) = getDimensions(array) return PeakProblem(array, (0, 0, rows, cols))
pb = createProblem(problemMatrix)print pb.startRowpb.printPeakProblem()
def crossProduct(list1, list2): ''' Returns all pairs with one item from the first list and one item from the second list. (Cartesian product of the two lists) The code is equivalent to the following list comprehension: return [(a, b) for a in list1 for b in list2] but for easier reading and analysis, we have included more explicit code. ''' answer = [] for a in list1: for b in list2: answer.append((a, b)) return answer
mid = pb.numCol // 2divider = crossProduct(range(pb.numRow), [mid])print dividerbestLoc = pb.getMaximum(divider)bestLoc
def algorithm1(problem): # if it's empty, we're done if problem.numRow <= 0 or problem.numCol <= 0: return None # the recursive subproblem will involve half the number of columns mid = problem.numCol // 2 # information about the two subproblems (subStartR, subNumR) = (0, problem.numRow) (subStartC1, subNumC1) = (0, mid) (subStartC2, subNumC2) = (mid + 1, problem.numCol - (mid + 1)) subproblems = [] subproblems.append((subStartR, subStartC1, subNumR, subNumC1)) subproblems.append((subStartR, subStartC2, subNumR, subNumC2)) # get a list of all locations in the dividing column divider = crossProduct(range(problem.numRow), [mid]) # find the maximum in the dividing column bestLoc = problem.getMaximum(divider) # see if the maximum value we found on the dividing line has a better # neighbor (which can't be on the dividing line, because we know that # this location is the best on the dividing line) neighbor = problem.getBetterNeighbor(bestLoc) # this is a peak, so return it if neighbor == bestLoc: return bestLoc # otherwise, figure out which subproblem contains the neighbor, and # recurse in that half sub = problem.getSubproblemContaining(subproblems, neighbor) result = algorithm1(sub) return problem.getLocationInSelf(sub, result)
# test algorithm1peak = algorithm1(pb)if pb.isPeak(peak): print(str(peak) + " => is a peak")
def algorithm2(problem, location = (0, 0)): # if it's empty, we're done if problem.numRow <= 0 or problem.numCol <= 0: return None nextLocation = problem.getBetterNeighbor(location) if nextLocation == location: # there is no better neighbor, so return this peak return location else: # there is a better neighbor, so move to the neighbor and recurse return algorithm2(problem, nextLocation)
# test algorithm2peak2 = algorithm2(pb)if pb.isPeak(peak2): print(str(peak2) + " => is a peak")
def algorithm4(problem, bestSeen = None, rowSplit = True): # if it's empty, we're done if problem.numRow <= 0 or problem.numCol <= 0: return None subproblems = [] divider = [] if rowSplit: # the recursive subproblem will involve half the number of rows mid = problem.numRow // 2 # information about the two subproblems (subStartR1, subNumR1) = (0, mid) (subStartR2, subNumR2) = (mid + 1, problem.numRow - (mid + 1)) (subStartC, subNumC) = (0, problem.numCol) subproblems.append((subStartR1, subStartC, subNumR1, subNumC)) subproblems.append((subStartR2, subStartC, subNumR2, subNumC)) # get a list of all locations in the dividing column divider = crossProduct([mid], range(problem.numCol)) else: # the recursive subproblem will involve half the number of columns mid = problem.numCol // 2 # information about the two subproblems (subStartR, subNumR) = (0, problem.numRow) (subStartC1, subNumC1) = (0, mid) (subStartC2, subNumC2) = (mid + 1, problem.numCol - (mid + 1)) subproblems.append((subStartR, subStartC1, subNumR, subNumC1)) subproblems.append((subStartR, subStartC2, subNumR, subNumC2)) # get a list of all locations in the dividing column divider = crossProduct(range(problem.numRow), [mid]) # find the maximum in the dividing row or column bestLoc = problem.getMaximum(divider) neighbor = problem.getBetterNeighbor(bestLoc) # update the best we've seen so far based on this new maximum if bestSeen is None or problem.get(neighbor) > problem.get(bestSeen): bestSeen = neighbor # return when we know we've found a peak if neighbor == bestLoc and problem.get(bestLoc) >= problem.get(bestSeen): return bestLoc # figure out which subproblem contains the largest number we've seen so far, # and recurse, alternating between splitting on rows and splitting on columns. sub = problem.getSubproblemContaining(subproblems, bestSeen) newBest = sub.getLocationInSelf(problem, bestSeen) result = algorithm4(sub, newBest, not rowSplit) return problem.getLocationInSelf(sub, result)
# test algorithm4peak4 = algorithm4(pb)if pb.isPeak(peak4): print(str(peak4) + " => is a peak")
- Peak Finding
- Peak finding
- 一维Peak finding 算法
- Codility-Peak
- Density Peak
- finding work
- Finding Software
- Finding Nemo
- Finding Nemo
- Finding Nemo
- VPS finding
- 【Python Challenge-5】peak
- [LeetCode] Find Peak Element
- Find Peak Element
- Leetcode:Find Peak Element
- Find Peak Element
- Find Peak Element
- Find Peak Element
- .NET基础--do-while
- Centos快速使用yum安装mysql
- 使用Nginx的proxy_cache缓存功能取代Squid[原创]
- SQlite命令行操作数据库
- 什么是最好的学习方法
- Peak Finding
- PHP Socket 编程过程详解
- hdu5438 拓扑+并查集 2015长春网赛
- 简单发送邮件工具类
- 实现支付宝接口时url的构造,主要解决服务器不支持https的问题
- 重写对象的equals方法和hascode方法
- shared_ptr 之循环引用 weak_ptr
- 网络拓扑结构
- Codeforces - 577B dp