- 所谓的局部高点就是在某个局部的地方的极值,这个不是全局最值,所以在寻找的时候,从哪里找?怎么找?效率就非常重要了。
- 基于没有现成的资料,因此特整理下思路,便于大家理解该算法。
- 简单算法:从第一个元素开始,判断其是否满足局部高点的条件,如果满足就返回该数的索引,否则判断下一个元素。如此循环判断输入序列的每一个元素直到找到一个局部高点为止。【提示:本文不考虑算法的异常检测等,没找到的时候怎么处理等手续请大家自行添加】
def findLocalHigh(A):
for i in range(len(A)):
if A[i-1] <= A[i] >= A[i+1]:
return i
else:
continue
A = [1, 2, 6, 5, 3, 7, 4]
i = findLocalHigh(A)
print(i)
最后输出结果:2
- 改进算法:前面的算法直观,容易实现,但不是最优的算法。改进的思路是减少查找次数。首先确定从哪个位置开始找,然后确定查找范围。可以借鉴二分法:从序列中间位置开始,这样每次搜索可以缩小一半的搜索范围。那有个问题,假设中间位置元素已知A[i],比较该元素和其相邻的元素之间的大小关系会有下面几种情况:
(1)A[i-1]<=A[i]>=A[i+1],也就是A[i]满足局部高点条件,完成任务,返回i。
(2)A[i]<A[i-1],也就是左边可能有局部高点,注意这里不是一定存在,很多教材上写了一定,举个反例:【8,7,6,5,3,7,4】你给我从这里的中间位置左边的里面找个局部高点?开玩笑!所以是可能,可能,可能。那这样从左边找吧先,可以借鉴递归的思路来构建你的算法。
(3)A[i]<A[i+1],也就是右边可能可能可能有局部高点,同理不是一定哈。那琢磨从右边找吧,同理(2)的方法思路,这里提醒下,一定存在,别我说啥就是啥好不?因为有个边界条件你忘记了吧?哈哈哈!A[-1]=A[n]=-inf,这个加上再试试,要批判精神,但是别忘记了条件,要不数学问题咋出来呢? - 改进算法代码:
def findHighSpot(A): # 寻找局部最高点
if len(A) == 1:
return 0
if len(A) == 2:
return int(A[0]<A[1])
i = len(A)//2
leftA = A[:i]
rightA = A[i+1:]
if A[i-1] <= A[i] >= A[i+1]:
return i
elif A[i] < A[i-1]:
return findHighSpot(leftA)
else:
return i + 1 + findHighSpot(rightA)
if __name__ == '__main__':
A = [1, 2, 6, 5, 3, 7, 4] # 输入input: 含有最高点高度的列表
i = findHighSpot(A) # 输出output: 返回最高点的位置
print(A) # 时间复杂度: O(log(n))
print(i)
- 更高级点的改进,这个有点好玩了:
def greater(A, B):
result = []
for i, j in zip(A, B):
if i > j:
result.append('True')
else:
result.append('False')
return result
def yys(r1, r2):
result = []
for i, j in zip(r1, r2):
if i == j and i == 'True':
result.append('True')
else:
result.append('False')
return result
def outLocalHigh(r3):
import numpy as np
result = np.array(r3)
result = np.where(result=='True')
return result
A = [1, 2, 6, 5, 3, 7, 4]
A_P = [2, 6, 5, 3, 7, 4, 4]
A_M = [1, 1, 2, 6, 5, 3, 7, 4]
r1 = greater(A, A_P)
r2 = greater(A, A_M)
r3 = yys(r1, r2)
r4 = outLocalHigh(r3)
print(r4[0][0])
print(r4[0][1])
- 仍然强调,就是为了单纯的完成教材上这个问题,所以设计简单,有纰漏的地方,请大家自行留言,互相改进。