找到列表中的所有山丘和山谷

时间:2018-06-01 07:45:43

标签: python algorithm

我正在编写一个函数来查找给定列表中的所有山峰和山谷。例如,[1,0,0,0,1]返回3,[0,1,0,1,0]返回5. [0,2,2,1,1,0,0]返回3.如果数字(或具有相同值的连续数字)大于或小于其两个邻居,它被认为是山丘或山谷。

以下是我的代码:

def hill_and_vally(s):
    if not s or len(s) < 2:
        return 0
    i = 0
    count = 0
    pre = None
    while i < len(s):
        if i == 0:
            while s[i] == s[i+1]:  # loop until value is different
                i += 1
            i += 1
            if i < len(s):       # check if it reaches the end 
                count += 1
                pre = s[i-1]     # track the previous value
        elif i == len(s) - 1:
            while s[i] == s[i-1]:  
                i -= 1
            i -= 1
            if i >= 0:
                count += 1
            break
        else:
            while s[i] == s[i+1]:
                i += 1
            i += 1
            if s[i] > s[i-1] and pre > s[i-1]:  # it is a valley
                count += 1
            elif s[i] < s[i-1] and pre < s[i-1]:  # it is a hill
                count += 1
            pre = s[i-1]
    return count

有人可以帮助我提高O(N)的复杂性。或者告诉我另一种方法,以更好的复杂性做到这一点?请给我看一些例子。提前致谢。

2 个答案:

答案 0 :(得分:4)

这是我将如何做到的:

  • 计算连续元素之间的差异d(从结果中删除0
  • 计算代码在d
  • 中更改的次数
  • 返回2加上该计数(因为即使以单调递增的顺序存在一个山丘和一个山谷)

在代码中:

def hill_and_vally(s):
    d=[x1-x0 for x0,x1 in zip(s,s[1:]) if x1!=x0]
    return 2+sum(d0*d1<0 for d0,d1 in zip(d,d[1:]))

当然可以使用for循环和索引来实现,但zip和列表推导更加pythonic。

zip(s,s[1:])是在列表中获取相邻元素对的常用方法。

试验:

>>> hill_and_vally([1,0,0,0,1])
3
>>> hill_and_vally([0,1,0,1,0])
5
>>> hill_and_vally([0,2,2,1,1,0,0])
3

答案 1 :(得分:0)

我知道这个问题已经很老了并且已经回答了,但是最近一次线性扫描就解决了这个问题:

HEX(CAST(HASH(BLOB('1'),0) as VARBINARY(128)))

它对所有输入都适用:

def solution(arr):
  prev = None
  curr = None
  total = 0

  for n in arr:
    if curr == None:
      curr = n
    else:
      if n != curr:
        if prev != None:
          if (prev < curr and n < curr) or (prev > curr and n > curr):
            total += 1
        else:
          prev = curr
          total += 1
        prev = curr
        curr = n

  if prev != curr:
    total += 1

  return total

它的作用是,它会跟踪先前的下坡/上坡,如果遇到其他适当的下坡/上坡,则会递增print(solution([1])) # 1 print(solution([1,2])) # 2 print(solution([1,1,1])) # 1 print(solution([1,2,1])) # 3 print(solution([1,2,6])) # 2 print(solution([1,2,3,4,4,3,4,4,5,6])) # 4 print(solution([-10,2,2,2,2])) # 2 print(solution([1,0,0,0,1])) # 3 print(solution([0,1,0,1,0])) # 5 print(solution([0,2,2,1,1,0,0])) # 3 计数器。