【问题标题】:Python: How to find longest continuous interval with connected interval start and endPython:如何找到具有连接间隔开始和结束的最长连续间隔
【发布时间】:2020-11-16 21:15:02
【问题描述】:

如何求最长连通区间链的长度?

例子:

[-4,1][1,5][2,10][3,5][1,3][3,8][8,12][5,11]

这里最长的链是:

[-4,1][1,3][3,8][8,12]

如您所见,当前间隔的结束应该是下一个间隔的开始。 我想找到最长链的长度:length=(12-(-4))=16

我认为这涉及递归?但是我不知道如何在 Python 中实现它。

提前致谢

【问题讨论】:

  • 这个问题可以通过在有向无环图中找到最长路径来解决。见en.wikipedia.org/wiki/…。那篇文章提到了寻找拓扑排序,但在这种情况下,这完全是微不足道的。只需按照端点的自然顺序对端点进行排序即可。
  • 看看这个:stackoverflow.com/questions/29320556/…。它回答了你的问题吗?
  • 由于我在这里找不到既简单又有效的方法,我只使用递归backtracking

标签: python


【解决方案1】:

动态编程:

from collections import defaultdict

intervals = [-4,1][1,5][2,10][3,5][1,3][3,8][8,12][5,11]
intervals = sorted(intervals, key=lambda x: (x[1], x[0]))  # will sort by end, then start

distances = defaultdict(int)
for start, end in intervals:
    # this is the key step: at each point, the max length interval up to here
    # is max combined length of all intervals that end here
    distances[end] = max(distances[end], distances[start] + end-start)
print(max(distances.values()))

【讨论】:

    【解决方案2】:

    稍微复杂一点的解决方案

    example = [[-4,1],[1,5],[2,10],[3,5],[1,3],[3,8],[8,12],[5,11]]
    
    # we create a simple tree structure
    tree = {}
    for v2 in example:
        tree[tuple(v2)] = ([v3 for v3 in example if v3[0] == v2[1]], 
                           [v3 for v3 in example if v3[1] == v2[0]])
    
    def is_ancestor(n1, n2, tree):
        """check if a node is ancestral to another"""
        if n1 in tree[tuple(n2)][1]:
            return True
        for n3 in tree[tuple(n2)][1]:
            return is_ancestor(n1, n3, tree)
        return False
    
    def get_longest(example, tree, result=None, v=None):
        """searches for longest path"""
        if not result:
            result = [[v]]
        for desc in tree[tuple(v)][0]:
            if result[-1][-1] not in tree[tuple(desc)][1]:
                result.append([r for r in result[-1] 
                               if is_ancestor(r, desc, tree)])
            result[-1].append(desc)
            get_longest(example, tree, result, desc)
        return result
    
    # check from each starting point
    max_dist = 0
    for n in example:
        for intervals in get_longest(example, tree, [], n):
            print (intervals, intervals[-1][1] , intervals[0][0])
            dist = intervals[-1][1] - intervals[0][0]
            if dist > max_dist:
                max_dist = dist
    print(max_dist)
    

    【讨论】:

      【解决方案3】:

      这是一种递归(回溯)方式:

      lst = [[-4,1], [1,5], [2,10], [3,5], [1,3], [3,8], [8,12], [5,11]]
      
      def longest(lst):
          mx = (0, [])
          for i in range(1, len(lst) -1):    # test for all following and acceptable elements
              if lst[i][0] == lst[0][1]:
                  add = longest(lst[i:])
                  if add[0] > mx[0]:         # keep "longest" chain 
                      mx = add
          #print(lst, mx)
          return (lst[0][1] - lst[0][0] + mx[0], [lst[0]] + mx[1])
      
      # chain elements must be in increasing order
      print(longest(sorted(lst)))
      

      它按预期给出:

      (15, [[-4, 1], [1, 3], [3, 5], [5, 11]])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-08
        • 2019-09-21
        • 1970-01-01
        • 1970-01-01
        • 2017-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多