找出数量不同的数字对,其总和等于某些' K' - PHP

时间:2017-12-31 06:17:16

标签: php arrays

给定一个数组,我想显示其总和等于K的不同元素对的计数 - 我已编写如下代码,但我无法正确使用array_diff:\

<?PHP
function numberOfPairs($a, $k) {
    $cnt = 0;
    for($i=0; $i<count($a); $i++){
        for($j=$i; $j<count($a); $j++){
            if($a[$i]+$a[$j] == $k){
                $arrRes[$i][0] = $a[$i];
                $arrRes[$i][1] = $a[$j];
                $cnt++;
            }
        }
    }
    sort($arrRes);
    //print $cnt;
    $d = $cnt;
    for($i=0; $i<count($arrRes); $i++){
        for($j=0; $j<count($arrRes); $j++){
            $diff = array_diff($arrRes[$i], $arrRes[$j]);
            if($diff == null)
                $d += 1;
        }
    }
    print $d;
}

$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a, $k);
?>

这里,总和等于12的输出数组,即$ arrRes的结果是 -

[0] => Array ( [0] => 3 [1] => 9 ) 
[1] => Array ( [0] => 6 [1] => 6 ) 
[2] => Array ( [0] => 6 [1] => 6 ) 
[3] => Array ( [0] => 9 [1] => 3 )

计数为4,但计数应为2,因为(6,6)和(3,9)是唯一不同的对。

4 个答案:

答案 0 :(得分:2)

您可以通过使用php中的数组是散列图的事实来简化您的解决方案:

function numberOfPairs($a, $k) {
    $used=[];
    for ($i=0; $i<count($a); $i++)
        for ($j=$i+1; $j<count($a); $j++) {
            $v1 = min($a[$i], $a[$j]);
            $v2 = max($a[$i], $a[$j]);
            if ($k == $v1+$v2)
                $used[$v1.'_'.$v2] = true;
        }
    return count($used);
}

$a = [6,6,3,9,3,5,1];
$k = 12;
echo numberOfPairs($a, $k);

答案 1 :(得分:1)

您可以使用已使用的数字创建一个平面数组并进行检查,以便不再使用in_array。

function numberOfPairs($a, $k) {
    $cnt = 0;
    $used=[];
    for($i=0; $i<count($a); $i++){
        for($j=$i; $j<count($a); $j++){
            if($a[$i]+$a[$j] == $k && !in_array($a[$i], $used) && !in_array($a[$i],$used)){
               $arrRes[$i][0] = $a[$i];
               $arrRes[$i][1] = $a[$j];
               $used[] = $a[$i];
               $used[] = $a[$j];
               $used = array_unique($used);
               $cnt++;
            }
        }
    }
    sort($arrRes);
    //print $cnt;
    // Not sure what the code below does, but I just left it the way it was.
    $d = $cnt;
    for($i=0; $i<count($arrRes); $i++){
        for($j=0; $j<count($arrRes); $j++){
            $diff = array_diff($arrRes[$i], $arrRes[$j]);
            if($diff == null)
                $d += 1;
        }
    }
    print $d;
}

$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a, $k);

在这里试试https://3v4l.org/lDe5V

答案 2 :(得分:1)

对数组进行排序并从两端移动索引,直到它们不重叠,在接受的答案中得到O(n log n)而不是O(n ^ 2)

function numberOfPairs($a, $k) {
  sort($a);
  $i = 0;
  $j = count($a)-1;
  // save last inseted array to avoid duplicates
  $last = [];
  while($i < $j) {
    $s = $a[$i] + $a[$j];
    if($s == $k) {
      $t = [$a[$i++], $a[$j--]];
      // Check for duplicate
      if ($t != $last) {
        $d[] = [$a[$i++], $a[$j--]];
        $last = $t;
      }
    }
    elseif($s > $k) $j--;
    else $i++;
  }
  return $d;
}

demo

答案 3 :(得分:1)

这是我在给定数组和目标总和时找到不同加数对的方法。

  • array_count_values()将通过压缩重复的加数并将它们存储为键(以及它们的出现次数作为值)来减少输入数组的大小。
  • 调用
  • ksort()以确保以递增顺序处理加数。这对于避免处理超出数字集中点的加数非常重要。
  • 每次迭代,存储“小于或等于”k的一半的加数并且具有匹配的加数。
  • 当加数乘以2是“大于或等于”k时,请勿继续迭代。

代码:(Demo

function numberOfPairs($a,$k){
    $a=array_count_values($a);  // enable use of the very fast isset() function and avoid iterating duplicates
    ksort($a);  // order so that only the lower values need to be iterated
    foreach($a as $num=>$occur){
        if(($double=$num*2)>=$k){ // we are at or past the middle
            if($double==$k && $occur>1) $result[]=[$num,$k-$num];  // addends are equal and 2 exist, store before break
            break;
        }elseif(isset($a[$k-$num])){  // matching addend found, store & continue
            $result[]=[$num,$k-$num];
        }
    }
    var_export($result);
}

$a = [6,6,3,9,3,5,1];
$k = 12;
numberOfPairs($a,$k);

输出:

array (
  0 => 
  array (
    0 => 3,
    1 => 9,
  ),
  1 => 
  array (
    0 => 6,
    1 => 6,
  ),
)

array_count_values()可能是代码段中最昂贵的函数调用,但它将所有后续进程设置为快速,简洁,直接和逻辑(我认为,可读)。