Home  >  Article  >  Backend Development  >  A PHP interview question, let’s take a look

A PHP interview question, let’s take a look

WBOY
WBOYOriginal
2016-12-05 13:44:131040browse

<code class="php">$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
    ...
];</code>

Define a function and pass in $listData
If the elements in 111 are duplicated with the elements in 222/333/444..., return false
If the elements in 222 are the same as 111/333/444 ... If the elements inside are repeated, return false
If the elements inside 333, and the elements inside 111/222/444... are repeated, return false
If...

Allow the elements in 111/222/333/444 to be repeated and return true
Return true in other cases


Known:
$listData length is unknown
111/222/333/444... The length of
111/222/333/444... is unknown. The elements in

111/222/333/444... are strings and numbers


I implemented it myself, and I feel that the algorithm is terrible. Is there any other method?
<code class="php">function test ($array) {

    $tempValueList  = [];
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            $tempValueList[]    = $key . '~' . $value;
        }
    }
    $result         = true;
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            foreach ($tempValueList as $_value) {
                
                $pos    = strpos($_value, '~');
                $_key   = substr($_value, 0, $pos);
                $_val   = substr($_value, $pos + 1);

                if ($key == $_key) {

                    continue;
                }
                if ($_val == $value) {

                    $result = false;
                    break 3;
                }
            }
        }
    }

    return      $result;
}</code>

Reply content:
<code class="php">$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
    ...
];</code>


Define a function and pass in $listDataIf the elements in 111
are duplicated with the elements in 222/333/444..., return false If the elements in 222
are the same as 111/333/444 ... If the elements inside are repeated, return false If the elements inside 333
, and the elements inside 111/222/444... are repeated, return false

If...


Allow the elements in 111/222/333/444 to be repeated and return true

Return true in other cases


Known:
$listData length is unknown
111/222/333/444... The length of

111/222/333/444... is unknown. The elements in
111/222/333/444... are strings and numbers

I implemented it myself, and I feel that the algorithm is terrible. Is there any other method?

<code class="php">function test ($array) {

    $tempValueList  = [];
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            $tempValueList[]    = $key . '~' . $value;
        }
    }
    $result         = true;
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            foreach ($tempValueList as $_value) {
                
                $pos    = strpos($_value, '~');
                $_key   = substr($_value, 0, $pos);
                $_val   = substr($_value, $pos + 1);

                if ($key == $_key) {

                    continue;
                }
                if ($_val == $value) {

                    $result = false;
                    break 3;
                }
            }
        }
    }

    return      $result;
}</code>

After taking a look, the two previous answers are unusable. LZ is really miserable. .

My definition of subarray is a single array like ['a', 'b', 'c', 'a'].

My answer:

<code>$result = array();
foreach ($listData as $line) {
    //子数组内部去重,再组装回原来的格式
    $result[] = array_unique($line);
}

//子数组先去重再合并的结果数量 和 先合并子数组再去重的结果数量 做比较。
//如果是相同的,意味着不存在跨子数组的重复,只存在子数组内部重复,所以`True`
var_dump(count(array_merge(...$result)) === count(array_unique(array_merge(...$listData))));</code>

My answer calls system functions more times and looks simpler. However, a large part of functions such as PHP array_xxx have no performance advantages. If these functions are not used, the operating efficiency can be relatively improved.

Currently, @springhack is the most efficient. And it can maintain maximum efficiency in every situation.

Easy to understand auxiliary reference information:

Original data:

<code>$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j']
];
</code>

Then $result ends up looking like this:

<code>$listData = [
        '111' => ['a', 'b', 'c'],
        '222' => ['d', 'e', 'f', 'b'],
        '333' => ['g', 'h'],
        '444' => ['i', 'j']
];
</code>

The result of sub-array deduplication first and then merging

<code>Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
    [4] => e
    [5] => f
    [6] => b
    [7] => g
    [8] => h
    [9] => i
    [10] => j
)
</code>

Used to compare the quantity (number of array elements) with the above, the so-called "result of merging sub-arrays first and then removing duplicates":

<code>Array
(
    [0] => a
    [1] => b
    [2] => c
    [4] => d
    [5] => e
    [6] => f
    [9] => g
    [10] => h
    [11] => i
    [12] => j
)</code>

Loop once and find the intersection of the current element and all other elements. The code is as follows:

<code>    function isExistsInOther($data)
    {
        $temp = [];
        $isExists = true;
        foreach ($data as $key=>$value) {
            $temp = $data;
            unset($temp[$key]);
            if(!$isExists) break;
            @array_walk($temp,function($v,$k) use($value,&$isExists){
                if($isExists) {
                    $intersect = array_intersect($v,$value);
                    if(!empty($intersect)) {
                        $isExists = false;
                    }
                }
            });
        }
        return $isExists;
    }
    
    $listData = [
        '111' => ['a', 'k', 'c', 'a'],
        '222' => ['d', 'e', 'f', 'f', 'b'],
        '333' => ['g', 'e'],
        '444' => ['i', 'j']
    ];
    $result = isExistsInOther($listData);
    var_dump($result);
    //true  无交集
    //false 有交集</code>

<code>/**
 * [checkRepeat 检查每个key的数组值是否与其它的有重复值]
 * @param  [type] $listData [检查的数组]
 * @return [type]           [array]
 */
function checkRepeat($listData) {
    foreach($listData as $key =>$val) {
        $check_arr = $listData;
        // 删除当前key
        unset($check_arr[$key]);
        // 合并删除后的数组
        $check_arr = array_merge(...$check_arr);
        // 判断是否存在交集
        $rs[$key] = count(array_intersect($val, $check_arr)) > 0 ? false : true ;
    }
    return $rs;
}

$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],

];
$rs = checkRepeat($listData);</code>
<code>function check($arr)
{
  $chk = [];
  foreach ($arr as $k => $v)
    foreach ($v as $i)
    {
      if (isset($chk[$i] && $chk[$i] != $k)
        return false;
      $chk[$i] = $k;
    }
  return true;
}</code>

The claw machine code should be the most efficient, so you can debug it yourself.

Since the answers are given above, let me add to you, multi-dimensional array deduplication

<code>/**
 * 多维数组去重
 * @param array 
 * @return array
 */
function super_unique($array)
{
    $result = array_map("unserialize", array_unique(array_map("serialize", $array)));

    foreach ($result as $key => $value)
    {
        if ( is_array($value) ) {
            $result[$key] = super_unique($value);
        }
    }

    return $result;
}</code>

Multi-dimensional array deduplication

<code>$listData = array_values($listData);
foreach ($listData as $k => $v) {
    foreach ($listData as $n => $m) {
        if($k == $n) continue;
        if(array_intersect($v , $m)){
            echo $k.$n.'false <br>';
        }
        else{
            echo $k.$n.'true <br>';
        }
    }
}</code>

My answer (principle: loop to find intersection):

<code><?php
$list = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f','b'],
    '333' => ['g', 'h','c'],
    '444' => ['i', 'j']
];
function jiaoji($array){
    $listData = array_values($array);
    $list = [];
    for ($i = 0; $i < count($listData); $i++) {
        for ($j = $i+1; $j < count($listData); $j++) {
            $list[] = array_intersect($listData[$i],$listData[$j]);
        }
    }
    $result = array_filter($list);
    return count($result)==0;
}
var_dump(jiaoji($list));//bool(false)
?></code>

Can you understand it this way? As long as the values ​​in this array intersect with each other, false will be returned. . .

array_intersect() function seems to work. But the problem is to convert the values ​​in an array into a small array to pass values.

<code><?php
$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
    ...
];

function getArr($listData){
    $isUnsetFirstKey = false;
    $len = count($listData);
    if($len<=1) return false;
    $firstKey = key($listData);
    $firstArr = array_unique($listData[$firstKey]);
    $newList = $listData;
    unset($newList[$firstKey]);
    foreach ($newList as $key => $val) {
        $arr = array_unique($val);
        $newarr = array_merge($firstArr,$arr);
        if(count($newarr) != count(array_unique($newarr))){
            $isUnsetFirstKey = true;
            unset($newList[$key]);
            echo $key . "<br>";
        }
    }
    if($isUnsetFirstKey) echo $firstKey . "<br>";
    getArr($newList);
}

getArr($listData);
?></code>

Check out my answer, it’s amazing


One-dimensional arrays are similar to two-dimensional arrays. The judgment is made internally. The following is the method for two-dimensional arrays. One-dimensional arrays are skipped. 🎜Compare the array length before and after the array merging (then take unique)🎜
<code class="php">function check_repeat($arr){
    $after_arr = [];
    // 对比自身
    foreach($arr as $index => $value){
        $arr[$index] = $after_arr = array_unique($value);
        if(count($value) !== count($after_arr)){
            return true;
        }
    }
    // 对比其他
    $temp = array_shift($arr);
    $cnt  = count($temp);
    foreach ($arr as $index => $value) {
        $cnt += count($value);
        $temp = array_merge($temp, $value);
    }

    return $cnt !== count(array_unique($temp)) ? true : false;
}

$listData = [
    '111' => ['a', 'b', 'c',],
    '222' => ['d', 'e', 'f',],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
];

var_dump(check_repeat($listData));
</code>

<code>function test($listData) {
    $result = array_map('array_unique', $listData);
    foreach ($result as $key => $value) {
        $keys = array_values(array_diff(array_keys($result),[$key]));
        for($i = 0; $i <= count($keys); $i ++) {
            $data = array_merge_recursive($data,$result[$keys[$i]]);
            if ($i == (count($keys) -1) ) {
                $res = array_intersect($value, $data);
            }
        }
        $data = [];
    }
    return !empty($res) === true ? false : true;
}</code>

<code><?php

$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
];

$temp = array();
foreach ($listData as $key => $xxx) {
    foreach ($xxx as $value) {
        if (in_array($value, $temp)) {
            echo $value.' from '.$key.' is in array';
            exit();
        }
    }
    $temp = array_merge($temp, $xxx);
}
echo 'You should get a True!';
</code>

没几行,满足需求。

A PHP interview question, let’s take a look

还原之前那个
shiji 的答案

先array_pop,取出最后一项。再取items数组的并集。if并集与最后一项有交集则返回true(表重复)。循环执行。

根据 @大呜 的算法改良了一下。

<code>function checkRepeat2($listData)
{
    $check_arr = $listData;
    foreach ($listData as $key => $val) {
        //之前比较过的key无需再比较
        unset($check_arr[$key]);
        if ($check_arr) {
            // 合并删除后的数组,判断是否存在交集
            //As PHP 5.6 you can use array_merge + "splat" operator to reduce a bidimensonal array to a simple array:
            if (array_intersect($val, array_merge(...$check_arr))) {
                return false;
            }
        }
    }
    return true;
}</code>

不知道是不是这样:

<code>$new_arr = [];
foreach ($listData as $key => $value) {
    foreach ($value as $k => $v) {
        $kv = $k . $v;
        if (in_array($kv, $new_arr)) {
            echo '有重复';exit;
        } else {
            $new_arr[] = $kv;
        }
    }
}</code>
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn