繁体   English   中英

使用 PHP 从无向图中找到最大的权重总和

[英]Find largest sum of weights from an undirected graph using PHP

上周我参加了一次面试,我被分配了一个与undirected graph相关的问题,要使用PHP来解决。

我试图以我的方式解决它,并且在所有测试用例中都得到了预期的结果,但我没有资格,因为我参与解决它的方式不正确。

我也附上了我的解决方案。 如果有人能解决它,我将不胜感激。

问题如下:-

对于N verticesM edges的图,将范围[1..N]中的不同值分配给顶点,以使所有边端点处的值的总和最大。

给定一个由 N 个顶点组成的无向图,编号从1 到 NM edges 该图由两个长度为 M 的arrays A 和 B描述。 一对(A[K], B[K]), for K from 0 to M-1 ,描述了vertex A[K] and vertex B[K]之间的边。

您的任务是将range [1..N]中的所有值分配给图形的顶点,为每个顶点分配一个数字 这样做的方式是使边缘端点处的值的所有边缘的总和最大。

例如,给定N = 5 , A = [2, 2, 1, 2] , B = [1, 3, 4, 4] ,图有四个边: (2, 1), (2, 3), (1, 4), (2, 4) 为了获得最大的权重总和,您可以将以下值分配给顶点:3、5、2、4、1(分别分配给顶点3, 5, 2, 4, 1 1, 2, 3, 4, 5

在此处输入图像描述

通过这种方式,我们获得了所有边端点的值之和等于7 + 8 + 7 + 9 = 31

edge (2, 3): 7 = 5 (vertex 2) + 2 (vertex 3)
edge (2, 1): 8 = 5 (vertex 2) + 3 (vertex 1)
edge (1, 4): 7 = 3 (vertex 1) + 4 (vertex 4)
edge (2, 4): 9 = 5 (vertex 2) + 4 (vertex 4)

请注意,分配给顶点 5 的值对最终结果没有任何影响,因为它不是边的端点

写一个 function

function solution($N, $A, $B)

即,给定一个正的 integer N 和两个 arrays A , BM个正整数,返回边缘端点值的最大可能总和。

我的解决方案:-

<?php
    function solution($N, $A, $B) {
        // write your code in PHP7.0
        $edges = [];
        for ($i=0; $i < count($A); $i++) { 
            $k = [$A[$i], $B[$i]];
            $edges[] = $k;
        }

        $nodes_arr = array_merge($A, $B);
        $nodes_arr = array_unique($nodes_arr);
        $nodes_arr = array_values($nodes_arr);
        

        $val_arr = [];
        for( $d=1; $d<=$N; $d++ ) {
            $val_arr[] = $d;
        }
        rsort($val_arr);

        $values_all = [];
        $diff = count($val_arr) - count($nodes_arr);
        
        for( $l=0; $l<count($val_arr)-$diff; $l++ ) {
            $values_all[] = $val_arr[$l];
        }


        // NODES & VALUES are finalized
        $nodes_permutation = permutations($nodes_arr);
        $values_permutation = permutations($values_all);

        $max_sum = 0;
        $all_arr = [];

        foreach ($nodes_permutation as $v) {
            $nodes = explode(",", $v);
            $values = $values_all;

            for( $k =0; $k<count($edges); $k++ ) {
                $arr = [];
                $pointer = 0;
                for( $i=$k; $i<count($nodes); $i++ ) {
                    $arr[] = array(
                        'node' => (int) $nodes[$i],
                        'value' => $values[$pointer],
                        'pointer' => $pointer
                    );
                    $pointer++;
                }

                if( $k > 0 && count($nodes) > 1 ) {
                    for( $r=0; $r<$k; $r++ ) {
                        $arr[] = array(
                            'node' => (int) $nodes[$r],
                            'value' => $values[$pointer],
                            'pointer' => $pointer
                        );
                        $pointer++;
                    }
                }
                $all_arr[] = $arr;
            }
        }


        foreach ($values_permutation as $v) {
            $nodes = $nodes_arr;
            $values = explode(",", $v);

            for( $k =0; $k<count($edges); $k++ ) {
                $arr = [];
                $pointer = 0;
                for( $i=$k; $i<count($nodes); $i++ ) {
                    $arr[] = array(
                        'node' => (int) $nodes[$i],
                        'value' => $values[$pointer],
                        'pointer' => $pointer
                    );
                    $pointer++;
                }

                if( $k > 0 && count($nodes) > 1 ) {
                    for( $r=0; $r<$k; $r++ ) {
                        $arr[] = array(
                            'node' => (int) $nodes[$r],
                            'value' => $values[$pointer],
                            'pointer' => $pointer
                        );
                        $pointer++;
                    }
                }

                $all_arr[] = $arr;
            }
        }

        foreach ($all_arr as $key => $arr) {
            $sum = 0;
            foreach( $edges as $edge ) {
                $val_1 = getValue($arr, $edge[0]);
                $val_2 = getValue($arr, $edge[1]);
                $sum += $val_1 + $val_2;
            }

            if( $sum > $max_sum ) {
                $max_sum = $sum;
            }
        }
        return $max_sum;
    }

    function getValue($edge_arr, $node_to_find) {
        foreach ($edge_arr as $key => $value) {
            if( $node_to_find == $value['node'] ) {
                return $value['value'];
            }
        }
    }

    function permutations($array) {
        $list = array();
        
        $array_count = count($array);
        
        $number_of_permutations = 1;
        if ($array_count > 1) {
            for ($i = 1; $i <= $array_count; $i++) {
                $number_of_permutations *= $i;
            }
        }
    
        for ($i=0; count($list) < $number_of_permutations; $i++) {
            shuffle($array);
            $tmp = implode(',', $array);
            if (!isset($list[$tmp])) {
                $list[$tmp] = 1;
            }
        }
    
        ksort($list);
        $list = array_keys($list);
        return $list;
    }

    echo json_encode(solution(5, [2, 2, 1, 2], [1, 3, 4, 4]));
?>

该解决方案也很有效,但对于大数据似乎失败了。

<?php
    echo json_encode(solution());

    function solution() {
        $a = [2,2,1,2];
        $b = [1,3,4,4];
        $w = 5;

        $all_comb = permutations($w);

        $sum = 0;
        foreach ($all_comb as $key => $value) {
            $v = explode(",", $value);
            $result = edgeValueTotal($a, $b, $v);
            if( $result > $sum ) {
                $sum = $result;
            }
        }
        return $sum;
    }

    function edgeValueTotal($a, $b, $w){
        if( count($a) != count($b) && count($a) != count($w)-1 ) {
            return false;
        }

        $total = 0;
        foreach ($a as $k => $va) {
            $vb = $b[$k];
            $total += (int)$w[$va - 1] + (int)$w[$vb -1];
        }

        return $total;
    }

    function permutations($number) {
        $array = [];
        for ($i=1; $i <= $number; $i++) { 
            $array[] = $i;
        }

        $list = array();
        
        $array_count = count($array);
        
        $number_of_permutations = 1;
        if ($array_count > 1) {
            for ($i = 1; $i <= $array_count; $i++) {
                $number_of_permutations *= $i;
            }
        }
    
        for ($i=0; count($list) < $number_of_permutations; $i++) {
            shuffle($array);
            $tmp = implode(',', $array);
            if (!isset($list[$tmp])) {
                $list[$tmp] = 1;
            }
        }
    
        ksort($list);
        $list = array_keys($list);
        return $list;
    }
?>

以下是解决问题陈述的方法

  • 通过迭代 A[i] 和 B[i] 创建一个表示图顶点之间链接的邻接列表

  • 在每个顶点上为出度创建一个映射 - Map<Integer, Integer>

  • 现在,由于我们需要实现边权重的最大总和,我们应该将值 N 分配给具有最大出度的 1,然后将 N-1 分配给小于或等于 1,依此类推。 为此,我们需要按值降序对 Map 进行排序

  • 一旦我们完成分配,迭代边缘映射以根据所讨论的逻辑计算总和

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM