原題鏈接:703. 數據流中的第K大元素
本題主要可以用到最小堆。
剛拿到這個題,有下面倆個思路:
1、接受參數,設置類屬性,方便add()方法調用。
class KthLargest {
/**
* @param Integer $k
* @param Integer[] $nums
*/
static $nums;
public $k;
function __construct($k, $nums) {
$this->k = $k;
$this->nums = $nums;
}
/**
* @param Integer $val
* @return Integer
*/
function add($val) {
array_push($this->nums, $val);
rsort($this->nums);
return $this->nums[$this->k - 1];
}
}
但是,這樣有個問題,就是超出時間限制,因爲數據量很大的時候,在規定時間範圍,無法解決。
2、第一個思路,時間超限的原因是每次都要對$this->nums這個數組,進行重新排序,上次已經排序好的,還要再重新排一次,浪費時間。所以,下面的解法是,每次只保存,上次排序完的前k個元素。這次的進行排序的次數就減少了。時間也減少了。
class KthLargest {
/**
* @param Integer $k
* @param Integer[] $nums
*/
static $nums;
public $k;
function __construct($k, $nums) {
$this->k = $k;
$this->nums = $nums;
}
/**
* @param Integer $val
* @return Integer
*/
function add($val) {
array_push($this->nums, $val);
rsort($this->nums);
$this->nums = array_slice($this->nums, 0, $this->k);
return $this->nums[$this->k - 1];
}
}
運行上面的代碼,可以發現。超出輸出限制。時間超出限制,已經解決。輸出超限制。只好換個方法。看了看評論和題解後,發現可以用最小堆。
正確的解法:
繼承PHP的spl擴展類SplMinHeap。利用最小堆的性質,該最小堆的根結點一定是所有結點中最小的。所以,我們只需要維護K個元素大小的最小堆。只要是大於最小堆的根結點的值$this->top(),就移除該根結點的值$this->extract(),把該值插入最小堆$this->insert($val)。
class KthLargest extends SplMinHeap{
/**
* @param Integer $k
* @param Integer[] $nums
*/
static $nums;
public $k;
function __construct($k, $nums) {
$this->k = $k;
遍歷初始化數組,分別插入堆中
foreach ($nums as $v) {
$this->add($v);
}
}
/**
* @param Integer $val
* @return Integer
*/
function add($val) {
維持堆的大小爲k,當堆還未滿時,插入數據。
if ($this->count() < $this->k) {
$this->insert($val);
} elseif ($this->top() < $val) {
//當堆滿的時候,比較要插入元素和堆頂元素大小。大於堆頂的插入。堆頂移除。
$this->extract();
$this->insert($val);
}
return $this->top();
}
}
如有問題,請留言。歡迎指正。