1. 程式人生 > >【阿里筆試】阿里媽媽關鍵詞熱度排行 (PHP版)

【阿里筆試】阿里媽媽關鍵詞熱度排行 (PHP版)

阿里不招PHP!

阿里不招PHP!

阿里不招PHP!

重要的事情說三遍。。。

看到室友在做一個阿里巴巴一個筆試題,只能用C/C++,JAVA,Clang,Clang++什麼的,沒有Python和PHP,感覺有點懵逼。

題目大致是這樣的:

阿里媽媽有個關鍵詞列表,每行記錄由 “關鍵詞+空格+熱度值“ 組成,如 ”連衣裙 96“,現在商家給商品新增一個關鍵詞,要求在商家輸入這個關鍵詞後,顯示類關鍵詞的熱度排行,由高到低。

題目還有定義,什麼是類關鍵詞?即組成漢字完全一樣,順序不一樣,即”連衣裙“和”裙連衣“是類關鍵詞關係,和”長裙“就不是類關鍵詞關係

輸入:一個關鍵詞熱度列表,商家關鍵詞,所有的漢字使用GBK編碼

輸出:類關鍵詞熱度排行

思路很簡單,奈何java和C已經還給老師了,只能php寫一波。

思路 :將關聯詞列表沒個元素分割成關鍵詞和熱度值,作為陣列A的兩個元素。對關鍵詞的每個漢字取其編碼的十進位制值,按照數值大小降序拼接為字串K,對K取其MD5摘要值,作為一個新陣列的的Key,A作為該陣列的一個子陣列。對於Key相同的陣列都放到一個同一個陣列單元,最終將所有的Key對於的數組合併為一個數組D(合併之前需要對每個Key對應的子陣列按照熱度進行二位陣列排序),則該陣列即為查詢字典。商家輸入關鍵詞後,我們計算該關鍵詞的Key,再去D中按Key去子陣列即可。

以上只是我個人的思路,目光短淺,只看到了實現方式,沒有深入思考演算法的優化,如果有不恰當的地方,歡迎大佬們批評指正 

_(:з」∠)_

廢話就不多說了,看程式碼:

<?php   
class Test{
        
    public static function run()
    {
        $list = [
            '連衣裙 19',
            '連裙衣 97',
            '裙連衣 28',
            '衣裙連 14',
            '可樂口可 34',
            '可口可樂 74',
            '小米手機 78',
            '小手米機 98',
            '小米機手 63',
            '阿里巴巴 47',
            '阿巴里巴 71',
            '巴阿巴里 71',
        ];

        $key = '連衣裙';
        $re = $this->similarityKeys($list, $key);
        print_r(json_encode($re));
    }

    
    /**獲取相似關鍵詞的熱度排序
     * @param $list
     * @param $key
     * @return array|mixed
     */
    private function similarityKeys($list,$key)
    {
        $encoding = 'GBK';
        $dictionary = $this->preProcessor($list,$encoding);
        print_r($dictionary);
        $key = $this->getKeyMd5String($key,$encoding);
        if(key_exists($key,$dictionary))
            return $dictionary[$key];
        else
            return [];
    }

    /**關鍵詞列表預處理
     * @param $list
     * @param $encoding
     * @return array
     */
    private function preProcessor($list,$encoding)
    {
        $data = [];
        //將key的dec降序排列組成的字串的MD5值相同的項放到一個數組內
        foreach ($list as $item)
        {
            $re = explode(' ',$item);//分割出關鍵字key 和他的熱度值hot
            $hash_key = $this->getKeyMd5String($re[0],$encoding);
            $data[$hash_key][] = $re;//將該記錄加入陣列中
        }

        foreach ($data as $k=>&$v)//對每個類關鍵詞陣列按照熱度值倒序排列
            $v = $this->twoDimensionArraySort($v,1,false,false);

        return $data;
    }

    /**將關鍵詞的每個字轉為十進位制數字,按由大到小順序拼接後取其MD5摘要值
     * @param $key
     * @param $encoding
     * @return string
     */
    private function getKeyMd5String($key,$encoding)
    {
        $len = mb_strlen($key,$encoding);
        $tmp_keys = [];
        for ($i=0;$i<$len;$i++) //記錄關鍵字中每個字的hex所對應的十進位制值
            array_push($tmp_keys,hexdec(bin2hex(mb_substr($key,$i,1,$encoding))));
        arsort($tmp_keys);//陣列按照其value降序
        $new_key = '';
        foreach ($tmp_keys as $k)
            $new_key .= '_'.$k;
        return md5($new_key);
    }


    /**二維陣列排序
     * @param $data array 輸入陣列
     * @param $key string 內部陣列的排序鍵
     * @param bool $asc 是否升序
     * @param bool $keep_key 是否保留原來的鍵
     * @return array
     */
    function twoDimensionArraySort($data,$key,$asc=true,$keep_key=true)
    {
        $keys = [];
        foreach ($data as $k=>$v)
        {
            $keys[$k] = $v[$key];
        }
        if($asc)
            asort($keys);
        else
            arsort($keys);

        $re = [];
        foreach ($keys as $k=>$v)
        {
            if($keep_key)
                $re[$k] = $data[$k];
            else
                array_push($re,$data[$k]);
        }
        unset($data,$keys);
        return $re;
    }
}

Test::run();

處理之後的關鍵詞列表如下所示:

{
	"58eed1a48f954e80f259ffd7bdca334c": [
		["連裙衣", "97"],
		["裙連衣", "28"],
		["連衣裙", "19"],
		["衣裙連", "14"]
	],
	"2a47cf89f52470a936ff0ff4567b75e3": [
		["可口可樂", "74"],
		["可樂口可", "34"]
	],
	"e1600cc8d3dd627209cb843d82e78b74": [
		["小手米機", "98"],
		["小米手機", "78"],
		["小米機手", "63"]
	],
	"54cf875aaa8f111aaf12fc2d75cc5948": [
		["巴阿巴里", "71"],
		["阿巴里巴", "71"],
		["阿里巴巴", "47"]
	]
}

輸入搜尋關鍵詞”連衣裙“,得到結果:

[
	["連裙衣", "97"],
	["裙連衣", "28"],
	["連衣裙", "19"],
	["衣裙連", "14"]
]

GG