前K个高频单词(leetcode 692)

问题描述

给一非空的单词列表,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

示例 1:

输入: [“i”, “love”, “leetcode”, “i”, “love”, “coding”], k = 2
输出: [“i”, “love”]
解析: “i” 和 “love” 为出现次数最多的两个单词,均为2次。
注意,按字母顺序 “i” 在 “love” 之前。

示例 2:

输入: [“the”, “day”, “is”, “sunny”, “the”, “the”, “the”, “sunny”, “is”, “is”], k = 4
输出: [“the”, “is”, “sunny”, “day”]
解析: “the”, “is”, “sunny” 和 “day” 是出现次数最多的四个单词,出现次数依次为 4, 3, 2 和 1 次。

注意:
假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。
输入的单词均由小写字母组成。
来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/top-k-frequent-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    protected $heap = [];
    protected $len = null;
    /**
     * @param String[] $words
     * @param Integer $k
     * @return String[]
     */
    function topKFrequent($words, $k) {
        if (empty($words)) {
            return ;
        }
        //构建hashmap
        $map = [];
        foreach ($words as $w) {
            if (isset($map[$w])) {
                $map[$w] += 1;
            } else {
                $map[$w] = 1;
            }
        }

        $arr = [];
        foreach ($map as $word => $num) {
            $arr[] = [
                'word'  => $word,
                'num'   => $num
            ];
        }
        unset($map);

		$len = count($map);
        //构建heap
        for ($i=0; $i<$k; $i++) {
            $this->heap[] = $arr[$i];
        }
        $this->len = count($this->heap);

        $this->create_heap();

        //追加
        for ($i=$k; $i<$len; $i++) {
            if ($this->heap[0]['num'] < $arr[$i]['num']) {
                $this->heap[0] = $arr[$i];
                $this->adjust_heap(0, $len);
            } else if ($this->heap[0]['num'] == $arr[$i]['num']) {
                if ($this->heap[0]['word'] > $arr[$i]['word']) {
                    $this->heap[0] = $arr[$i];
                    $this->adjust_heap(0, $len);
                }
            } else {
                //nothing
            }
        }
        
        //排序
        $this->sort();
         $ret = [];
         foreach ($this->heap as $item) {
             $ret[] = $item['word'];
         }
         return $ret;
    }

    function create_heap()
    {
        $len = count($this->heap);
        for ($i=$len >> 1; $i>=0; $i--) {
            $this->adjust_heap($i);
        }
    }

    /**
     * 根index 调整某棵树的左右节点
     **/
    function adjust_heap($index)
    {
        $len = $this->len;
        if ($index >= $len) {
            return ;
        }

        $l = ($index << 1) + 1;
        $r = ($index << 1) + 2;
        $min = $index;

        if ($l < $len && $this->heap[$l]['num'] < $this->heap[$min]['num']) {
            $min = $l;
        }
        if ($l < $len && $this->heap[$l]['num'] == $this->heap[$min]['num'] && $this->heap[$l]['word'] > $this->heap[$min]['word']) {
            $min = $l;
        }

        if ($r < $len && $this->heap[$r]['num'] < $this->heap[$min]['num']) {
            $min = $r;
        }
        if ($r < $len && $this->heap[$r]['num'] == $this->heap[$min]['num'] && $this->heap[$r]['word'] > $this->heap[$min]['word']) {
            $min = $r;
        }

        if ($min != $index) {
            list($this->heap[$index], $this->heap[$min]) = [$this->heap[$min], $this->heap[$index]];
            $this->adjust_heap($min);
        }
    }

    public function sort()
    {
        $len = count($this->heap);
        for ($i = $len - 1; $i>0; $i--) {
            list($this->heap[0], $this->heap[$i]) = [$this->heap[$i], $this->heap[0]];
            $this->len -= 1;
            $this->adjust_heap(0);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值