问题描述
给一非空的单词列表,返回前 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);
}
}
}