[英]Find largest sum of weights from an undirected graph using PHP
上周我参加了一次面试,我被分配了一个与undirected graph
相关的问题,要使用PHP
来解决。
我试图以我的方式解决它,并且在所有测试用例中都得到了预期的结果,但我没有资格,因为我参与解决它的方式不正确。
我也附上了我的解决方案。 如果有人能解决它,我将不胜感激。
问题如下:-
对于N vertices和M edges的图,将范围[1..N]中的不同值分配给顶点,以使所有边端点处的值的总和最大。
给定一个由 N 个顶点组成的无向图,编号从1 到 N和M 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
, B
的M
个正整数,返回边缘端点值的最大可能总和。
我的解决方案:-
<?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.