>  기사  >  백엔드 개발  >  PHP 면접 질문, 살펴보겠습니다

PHP 면접 질문, 살펴보겠습니다

WBOY
WBOY원래의
2016-12-05 13:44:131040검색

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

함수 정의, $listData 전달
111의 요소가 222/333/444...의 요소와 중복되는 경우 false 반환
222의 요소인 경우, If 111/333/444...의 요소가 중복되면 false를 반환합니다.
333의 요소가 111/222/444...의 요소와 중복되면 false를 반환합니다.
..

111/222/333/444의 요소가 반복되도록 허용하고 true를 반환합니다.
다른 경우에는 true를 반환합니다


알려짐:
$listData의 길이를 알 수 없습니다.
111/222/333/444의 길이를 알 수 없습니다.
111/222/333/444의 요소입니다. .. 문자는 문자열과 숫자입니다



직접 구현해봤는데 알고리즘이 형편없네요.

<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>

답글 내용:

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

함수 정의, $listData 전달
111의 요소가 222/333/444...의 요소와 중복되는 경우 false 반환
222의 요소인 경우, If 111/333/444...의 요소가 중복되면 false를 반환합니다.
333의 요소가 111/222/444...의 요소와 중복되면 false를 반환합니다.
..

111/222/333/444의 요소가 반복되도록 허용하고 true를 반환합니다.
다른 경우에는 true를 반환합니다


알려짐:
$listData의 길이를 알 수 없습니다.
111/222/333/444의 길이를 알 수 없습니다.
111/222/333/444의 요소입니다. .. 문자는 문자열과 숫자입니다



직접 구현해봤는데 알고리즘이 형편없네요.

<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>

살펴보니 앞의 두 답변은 사용할 수 없습니다. LZ는 정말 비참합니다. .

내가 정의한 하위 배열은 ['a', 'b', 'c', 'a']와 같은 단일 배열입니다.

내 답변:

<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>

내 대답은 시스템 함수를 더 많이 호출하고 더 단순해 보이지만 PHP array_xxx와 같은 함수의 대부분은 이러한 함수를 사용하지 않으면 상대적으로 작업 효율성이 향상될 수 있습니다.

현재는 @springhack이 가장 효율적입니다. 그리고 모든 상황에서 최대의 효율성을 유지할 수 있습니다.

이해하기 쉬운 보조 참고 정보:

원본 데이터:

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

그러면 $result는 다음과 같이 됩니다.

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

하위 어레이 중복 제거 후 병합 결과

<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>

수량(배열 요소 수)을 위와 비교하는 데 사용되는 소위 "하위 배열을 먼저 병합한 후 중복 제거한 결과":

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

한 번 반복하여 현재 요소와 다른 모든 요소의 교차점을 찾습니다.

<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>

클로 머신 코드 워드가 가장 효율적이므로 직접 디버깅할 수 있습니다.

위에 답변이 주어졌으므로 다차원 배열 중복 제거를 추가하겠습니다

<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>

다차원 배열 중복 제거

<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>

내 대답(원리: 교차점 찾기를 반복):

<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>

이렇게 이해가 되시나요? 이 배열의 값이 서로 교차하는 한 false가 반환됩니다. . .
array_intersect() 함수가 작동하는 것 같습니다. 그런데 문제는 배열의 값을 작은 배열로 변환하여 값을 전달하는 것입니다.

<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>

제 답변을 확인해 보세요. 정말 놀랍습니다

1차원 배열은 2차원 배열과 유사합니다. 2차원 배열의 경우 다음 방법으로 건너뜁니다.
배열 길이 전후를 비교합니다. 배열 병합(그런 다음 고유한 값을 취함)

<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>

没几行,满足需求。

PHP 면접 질문, 살펴보겠습니다

还原之前那个
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>
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.