给定父级数组和值数组。在树中找到最佳可能的总和

时间:2019-02-02 14:04:35

标签: data-structures tree

给出父级数组,使得parent [i] = j其中j是父级和Value数组。需要找到最佳可能的总和。

根节点的父节点为-1。

最佳可能总和是其中一条树路径的最大总和。

Ex)

 Integer[] parent = new Integer[] { -1, 0, 0, 2, 3 };
 Integer[] values = new Integer[] { 0, 4, 6, -11, 3 };

     (0/0)----(1/4)
     |
     |
     (2/6)
     |
     |
     (3/-11)
     |
     |
     (4/3)

此处,路径2-> 0-> 1的最大和为6 + 0 + 4 = 10。

我尝试用dfs方法解决它。但不确定是否适用于所有情况。下面是我的代码。它给出了所有可能的和。我们可以从中获取最大收益。

    package com.programs.algo;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;

    public class BestPossibleSum {

        static class Node<T> {

        T label;
        T data;
        List<Node<T>> nodes;
       }

public static void main(String[] args) {

    Integer[] parent = new Integer[] { -1, 0, 0, 1, 1, 3, 5 };
    Integer[] values = new Integer[] { 0, 4, 6, -11, 3, 10, 11 };

    List<Integer> list1 = new ArrayList<>(Arrays.asList(parent));
    List<Integer> list2 = new ArrayList<>(Arrays.asList(values));
    bestPossibleSum(list1, list2);
}

static List<Node<Integer>> tree = new ArrayList<>();

private static void bestPossibleSum(List<Integer> list1, List<Integer> list2) {
    int adj[][] = new int[list1.size()][list1.size()];
    createTree(list1, list2, adj);
    List<Integer> traversedNodes = new ArrayList<>();
    List<Integer> sumOfraversedNodes = new ArrayList<>();

    for (int i = 0; i < adj.length; i++) {
        dfs(tree.get(i), traversedNodes, sumOfraversedNodes);
        traversedNodes.clear();
    }

    System.out.println(sumOfraversedNodes);
}

private static void dfs(Node<Integer> tree, List<Integer> traversedNodes, List<Integer> sums) {
    if (!traversedNodes.contains(tree.label)) {
        traversedNodes.add(tree.label);
        sums.add(getSum(traversedNodes));
        for (Node<Integer> child : tree.nodes) {
            dfs(child, traversedNodes, sums);
        }
    }
}

private static Integer getSum(List<Integer> traversedNodes) {
    System.out.println(traversedNodes);
    return traversedNodes.stream().reduce(0, Integer::sum);
}

private static void createTree(List<Integer> parent, List<Integer> values, int[][] adj) {

    for (int i = 0; i < parent.size(); i++) {
        Node<Integer> node = new Node<>();
        node.label = i;
        node.data = values.get(i);
        node.nodes = new ArrayList<>();
        tree.add(i, node);
    }

    for (int i = 0; i < parent.size(); i++) {
        if (parent.get(i) != -1) {
            adj[parent.get(i)][i] = 1;
            adj[i][parent.get(i)] = 1;
            tree.get(parent.get(i)).nodes.add(tree.get(i));
        }
    }

    tree.forEach(t -> {
        System.out.println(t.label);
        System.out.println(t.nodes.stream().map(m -> m.label).collect(Collectors.toList()));
    });
    // System.out.println(Arrays.deepToString(adj));
}

}

3 个答案:

答案 0 :(得分:0)

我会将您的问题分为两个不同的问题:

  1. 根据您的数据构建树
  2. 找到最大金额

我用PHP编写了代码,但是您可以将其转换为所需的任何语言(我的JAVA技能有点生锈...)

构建树

$parent = array( -1, 0, 0, 2, 3 );
$values = array(0, 4, 6, -11, 3 );

function getNode($id, $data) {
    return array("id" => $id, "data" => $data, "childs" => array());
}
function addToTree($node, &$root, $parentsId) {
    if ($parentsId == -1)
        $root = $node;
    else if ( $root["id"] == $parentsId)
        $root["childs"][] = $node;
    else
        foreach($root["childs"] as &$child)
            addToTree($node, $child, $parentsId);
}

$root = null;
for($i = 0; $i < count($parent); $i++) {
    addToTree(getNode($i, $values[$i]), $root, $parent[$i]);
}

现在root如果包含“树状”数据。请注意,只有当节点以正确的顺序给出并且它不支持多根(假定是树而不是森林)时,此代码才有效

查找最大路径

function maxPath($node) {
    $sum = $node["data"];
    foreach($node["childs"] as $child) {
        $s = maxPath($child);
        if ($s > 0) // if its not positive then don't take it
            $sum += $s;
    }
    return $sum;
}

此递归函数将获取您的最大和路径。请注意,这将允许每个节点有多个子节点,并且路径也可以具有星形。

答案 1 :(得分:0)

发布Java代码,将其视为具有左右节点的树。

https://www.geeksforgeeks.org/construct-a-binary-tree-from-parent-array-representation/

https://www.geeksforgeeks.org/find-maximum-path-sum-in-a-binary-tree/

  private static int maxSum(Node<Integer> btree, Result result) {

    if (btree == null)
        return 0;
    int l = maxSum(btree.left, result);
    int r = maxSum(btree.right, result);

    System.out.println(l + " " + r + " " + btree.data);
    int maxSingle = Math.max(Math.max(l, r) + btree.label, btree.label);
    int maxTop = Math.max(l + r + btree.label, maxSingle);

    result.val = Math.max(maxTop, result.val);
    return maxSingle;
}

private static Node<Integer> createBinaryTree(Integer[] parent, Node<Integer> root) {
    Map<Integer, Node<Integer>> map = new HashMap<>();

    for (int i = 0; i < parent.length; i++) {
        map.put(i, new Node<>(i));
    }

    for (int i = 0; i < parent.length; i++) {
        if (parent[i] == -1) {
            root = map.get(i);
        } else {
            Node<Integer> par = map.get(parent[i]);
            Node<Integer> child = map.get(i);
            if (par.left == null) {
                par.left = child;
            } else {
                par.right = child;
            }
        }
    }

    return root;
}

答案 2 :(得分:0)

1。通过以下步骤将给定的父数组转换为图: unordered_map >>图;

for(int i=0;i<n;i++){
    if(parents[i]!=-1){
    graph[parents[i]].push_back({i,values[i]});
    graph[i].push_back({parents[i],values[parents[i]]});
    }
}

2。在每个节点上应用DFS并检查最大路径总和

vector<bool> vis(n,false);
int res=0;
for(int i=0;i<n;i++){
    vis.clear();
    dfs(i,vis,mp,values,res);
}
  1. DFS功能

void dfs(int src,vector&vis,unordered_map

vector<pair<int,int>>>&graph,vector<int>&values,int res){
res+=values[src];
ans=max(ans,res);
vis[src]=true;

for(int i=0;i<graph[src].size();i++){
    if(!vis[graph[src][i].first]){
        dfs(graph[src][i].first,vis,graph,values,res);
    }
}
vis[src]=false;
}

C ++代码:

#include<bits/stdc++.h>  
using namespace std;

int ans=INT_MIN;

void dfs(int src,vector<bool>&vis,unordered_map<int,
vector<pair<int,int>>>&graph,vector<int>&values,int res){
res+=values[src];
ans=max(ans,res);
vis[src]=true;

for(int i=0;i<graph[src].size();i++){
    if(!vis[graph[src][i].first]){
        dfs(graph[src][i].first,vis,graph,values,res);
    }
}

vis[src]=false;
}

int maxPathSum(vector<int>&parents,vector<int>&values){
int n=parents.size();
unordered_map<int,vector<pair<int,int>>> mp;

for(int i=0;i<n;i++){
    if(parents[i]!=-1){
    mp[parents[i]].push_back({i,values[i]});
    mp[i].push_back({parents[i],values[parents[i]]});
    }
}

vector<bool> vis(n,false);
int res=0;
for(int i=0;i<n;i++){
    vis.clear();
    dfs(i,vis,mp,values,res);
}

return ans;
}

int main(){
vector<int> parent = {-1,0,0,2,3};    //{-1,0,1,2,0};
vector<int> values = {0,4,6,-11,3};   //{-2,10,10,-3,10};
cout<<maxPathSum(parent,values)<<endl;
return 0;
}