返回具有相同值的节点的最长路径

时间:2018-05-08 23:30:14

标签: python python-3.x

我刚刚研究了一些谷歌面试问题,我在网上偶然发现了一个我似乎无法理解的问题

考虑具有N个节点的无向​​树,编号从1到N.每个节点都有一个与之关联的标签,这是一个整数值。不同的节点可以具有相同的标签。编写一个函数,给定长度为N的零索引数组A,其中A [j]是树中第(j + 1)节点的标签值,以及长度为K =(N)的零索引数组E. - 1)* 2描述树的边缘,返回最长路径的长度,使得该路径上的所有节点具有相同的标签。长度是该路径中的边数。

示例:

A = [1,1,1,2,2] E = [1,2,1,3,2,4,2,5]

此树如下所示。节点遵循表单标签值。

----------1, 1

-----1, 2        1, 3

2, 4      2, 5

该函数应返回2,因为最长的路径是2→1> 3,并且此路径中有2条边。

假设1 <= N <= 1000并且阵列A的每个元素是[1,1000000000]范围内的整数。

你有什么打算解决这个问题?谢谢!

3 个答案:

答案 0 :(得分:1)

这是我的建议。我没有彻底检查过它。

from collections import defaultdict

A = [1, 1, 1, 2, 2] 

E = [1, 2, 1, 3, 2, 4, 2, 5]

d = defaultdict(list)
it = iter(E)
for k, v in zip(it, it):
    d[k].append(v)
    d[v].append(k)

leaves = [k for k, v in d.items() if len(v) == 1]

def len_path(node, length=0, coming_from=None):

    max_loc_len = length
    loc_data = A[node-1]

    available_nodes = {i: A[i-1] for i in d[node]}
    available_nodes.pop(coming_from, None)

    for i, i_data in available_nodes.items():
        cumul = length + 1 if loc_data == i_data else 0
        loc_len = len_path(i, cumul, node)
        if loc_len > max_loc_len:
            max_loc_len = loc_len 

    return max_loc_len

max_len = max([len_path(leaf) for leaf in leaves])

更复杂的搜索,避免两次计算相同的路径:

# ...
def len_path(node, length=0, coming_from=None, fork=False):

    max_loc_len = length
    loc_data = A[node-1]

    available_nodes = {i: A[i-1] for i in d[node]}
    available_nodes.pop(coming_from, None)

    matching_nodes = [k for k, v in available_nodes.items()
                         if v == loc_data and k not in leaves[:explored]]
    if len(matching_nodes) > 1:
        fork = True

    if not available_nodes and not fork and node in leaves[explored:]:
        # Reached an unexplored leaf without forks on the path, 
        # hence no need to explore it later
        leaves.remove(node)

    for i, i_data in available_nodes.items():
        cumul = length + 1 if loc_data == i_data else 0
        loc_len = len_path(i, cumul, node, fork)
        if loc_len > max_loc_len:
            max_loc_len = loc_len 

    return max_loc_len

explored = 0
max_len =0

while explored < len(leaves):
    length = len_path(leaves[explored])
    if length > max_len:
        max_len = length
    explored += 1

答案 1 :(得分:0)

一种方法可以像这样:

  • 根据输入内容建立邻接表
  • 选择一个节点,并找到具有相同标签的该节点的子树的直径

最大直径将是答案

答案 2 :(得分:0)

更简单的方法:

import operator

A = [1, 1, 1 ,2, 2]

d = {}
final = {}

def func(node, val):
    if len(A) < node: return 0
    if A[node-1] == val: return 1
    else: return 0

for idx, a in enumerate(A):
    id = idx+1
    d[id] = (a,func(id+id, a),func((id*2)+1 , a))

for val in d.values():
    i1,i2,i3 = val
    if i1 not in final:
        final[i1] = 0
    final[i1] += i2 + i3

print(max(final.iteritems(),key = operator.itemgetter(1))[1])