一個php的面試題,大家看看

來源:互聯網
上載者:User
$listData = [    '111' => ['a', 'b', 'c', 'a'],    '222' => ['d', 'e', 'f', 'f', 'b'],    '333' => ['g', 'h'],    '444' => ['i', 'j'],    ...];

定義一個函數,傳入$listData
如果111裡面的元素,和 222/333/444... 裡面的元素有重複,返回false
如果222裡面的元素,和 111/333/444... 裡面的元素有重複,返回false
如果333裡面的元素,和 111/222/444... 裡面的元素有重複,返回false
如果 ...

允許 111/222/333/444 自己裡面的元素重複,返回true
其他情況返回true

已知:
$listData長度未知
111/222/333/444... 的長度未知
111/222/333/444... 裡的元素為字串和數字

我自己實現了一下,感覺演算法很糟,請問有沒有其他方法

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

回複內容:

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

定義一個函數,傳入$listData
如果111裡面的元素,和 222/333/444... 裡面的元素有重複,返回false
如果222裡面的元素,和 111/333/444... 裡面的元素有重複,返回false
如果333裡面的元素,和 111/222/444... 裡面的元素有重複,返回false
如果 ...

允許 111/222/333/444 自己裡面的元素重複,返回true
其他情況返回true

已知:
$listData長度未知
111/222/333/444... 的長度未知
111/222/333/444... 裡的元素為字串和數字

我自己實現了一下,感覺演算法很糟,請問有沒有其他方法

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

看了看,之前的那倆答案都是不能用的。LZ真是苦命。。

我對子數組的定義是像 ['a', 'b', 'c', 'a'] 這樣的單個數組。

我的答案:

$result = array();foreach ($listData as $line) {    //子數組內部去重,再組裝回原來的格式    $result[] = array_unique($line);}//子數組先去重再合并的結果數量 和 先合并子數組再去重的結果數量 做比較。//如果是相同的,意味著不存在跨子數組的重複,只存在子數組內部重複,所以`True`var_dump(count(array_merge(...$result)) === count(array_unique(array_merge(...$listData))));

我這個答案調用系統函數次數比較多,看起來簡潔一些,但是PHP array_xxx 這類函數很大一部分效能是不具備優勢的,如果不用這些函數,能相對程度提高運行效率。

目前, @springhack 的效率是最高的。而且在各種情形下都能保持最高效率。

方便理解的輔助參考資訊:

未經處理資料:

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

然後 $result 最終是這樣的:

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

子數組先去重再合并的結果

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

用於和上面進行數量(數組元素數量)比較的,所謂的“先合并子數組再去重的結果”:

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

迴圈一次,當前元素和其它所有元素求交集,代碼如下:

    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 有交集

/** * [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);

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

爪機碼字,應該是效率最高的,自己調試下。

既然上面都給了答案,我給你補充一下,多維陣列去重

/** * 多維陣列去重 * @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;}

多維陣列去重

$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 
'; } else{ echo $k.$n.'true
'; } }}

我的答案(原理:迴圈求交集):

 ['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)?>

能不能這樣理解 只要這個數組裡面的值相互之間有交集 那就返回false 。。。
array_intersect()函數好像可以用。但是問題就是在於將一個數組裡面的值變成小數組傳值。

 ['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 . "
"; } } if($isUnsetFirstKey) echo $firstKey . "
"; getArr($newList);}getArr($listData);?>

我的答案,看看吧,很厲害的

一維數組和二維數組類似, 在內部做判斷, 下面是二維數組的方法, 一維數組略過
比較數組合并之前和之後(之後取unique)的數組長度

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

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

 ['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!';

沒幾行,滿足需求。

還原之前那個
shiji 的答案

先array_pop,取出最後一項。再取items數組的並集。if並集與最後一項有交集則返回true(表重複)。迴圈執行。

根據 @大嗚 的演算法改良了一下。

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

不知道是不是這樣:

$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;        }    }}
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.