namespace map;
/**
* 基於搜索二叉樹實現的映射類
* @package map
*/
class BSTMap implements Map
{
private $root;
private $size;
public function __construct()
{
$this->root = null;
$this->size = 0;
}
public function isEmpty()
{
return $this->size == 0;
}
public function getSize()
{
return $this->size;
}
public function contains($key)
{
return $this->getNode($this->root, $key) != null;
}
/**
* 添加元素到而二分搜索樹
* @param mixed $key
* @param mixed $value
*/
public function add($key, $value)
{
$this->root = $this->addNode($this->root, $key, $value);
}
/**
* 往以node爲根的二分搜索樹添加元素(key,value),遞歸算法
* 返回插入新節點後二分搜索樹的根
* @param BSTNode|null $node
* @param null|mixed $key 映射的鍵
* @param null|mixed $value 映射的值
* @return BSTNode
*/
private function addNode(BSTNode $node = null, $key = null, $value = null)
{
if ($node == null) {
$this->size++;
return new BSTNode($key, $value);
}
if ($key < $node->key)
$node->left = $this->addNode($node->left, $key, $value);
else if ($key > $node->key)
$node->right = $this->addNode($node->right, $key, $value);
else // $key == $node->key
$node->value = $value;
return $node;
}
/**
* 返回以node爲根的二分搜索樹中key所在的節點
* @param BSTNode|null $node
* @param null|mixed $key
* @return BSTNode|null
*/
private function getNode(BSTNode $node = null, $key = null)
{
if ($node == null)
return null;
if ($key == $node->key)
return $node;
else if ($key < $node->key)
return $this->getNode($node->left, $key);
else // $key > $node->key
return $this->getNode($node->right, $key);
}
public function set($key, $newValue)
{
$node = $this->getNode($this->root, $key);
if ($node == null)
throw new \InvalidArgumentException($key . " does't exist");
$node->value = $newValue;
}
/**
* 獲取鍵爲key的值
* @param $key
* @return mixed|null
*/
public function get($key)
{
$node = $this->getNode($this->root, $key);
return $node == null ? null : $node->value;
}
/**
* 從二分搜索樹中刪除鍵爲key的節點
* @param $key
* @return mixed|null
*/
public function remove($key)
{
$node = $this->getNode($this->root, $key);
if ($node == null)
return null;
$this->root = $this->removeNode($this->root, $key);
return $node->value;
}
/**
* 從以node爲根節點的二分搜索樹中刪除鍵爲key的節點,遞歸算法
* 返回刪除節點後新的二分搜索樹的根節點
* @param BSTNode|null $node
* @param null $key
* @return BSTNode|null
*/
private function removeNode(BSTNode $node = null, $key = null)
{
if ($node == null)
return null;
if ($key < $node->key) {
$node->left = $this->removeNode($node->left, $key);
return $node;
} else if ($key > $node->key) {
$node->right = $this->removeNode($node->right, $key);
return $node;
} else {
if ($node->left == null) {
$rightNode = $node->right;
$node->right = null;
$this->size--;
return $rightNode;
}
if ($node->right == null) {
$leftNode = $node->left;
$node->left = null;
$this->size--;
return $leftNode;
}
$successor = $this->minNum($node->right);
$successor->right = $this->removeMin($node->right);
$successor->left = $node->left;
$node->right = $node->left = null;
return $successor;
}
}
/**
* 查找最小元素
* @param BSTNode|null $node
* @return BSTNode
*/
private function minNum(BSTNode $node = null)
{
if ($node->left == null)
return $node;
return $this->minNum($node->left);
}
/**
* 刪除最小元素
* @param BSTNode|null $node
* @return BSTNode|null
*/
private function removeMin(BSTNode $node = null)
{
if ($node->left == null) {
$rightNode = $node->right;
$node->right = null;
$this->size--;
return $rightNode;
}
$node->left = $this->removeMin($node->left);
return $node;
}
}
namespace map;
interface Map
{
function add($key, $value);
function remove($key);
function contains($key);
function get($key);
function set($key, $newValue);
function getSize();
function isEmpty();
}
namespace map;
/**
* 二分搜索樹的節點類
* @package map
*/
class BSTNode
{
/**
* 左孩子
* @var BSTNode
*/
public $left;
/**
* 右孩子
* @var BSTNode
*/
public $right;
/**
* 映射鍵
* @var mixed
*/
public $key;
/**
* 映射值
* @var mixed
*/
public $value;
/**
* BSTNode constructor.
* @param $key
* @param $value
*/
public function __construct($key, $value)
{
$this->key = $key;
$this->value = $value;
$this->left = null;
$this->right = null;
}
}
複製代碼
測試用例1node
$words=[
'jack','jackson','jack','huan','wang','li','jack','li','king','tom'
];
$map = new \map\BSTMap();
foreach ($words as $word){
if($map->contains($word))
$map->set($word,$map->get($word)+1);
else
$map->add($word,1);
}
echo 'total words:'.count($words),'<br/>';
echo 'total different words:'.$map->getSize(),'<br/>';
echo 'Frenquency of jack: '. $map->get('jack'),'<br/>';
echo 'Frenquency of li: '. $map->get('li'),'<br/>';
echo 'Frequency of huan: '. $map->get('huan'),'<br/>';
複製代碼
測試用例2算法
給定兩個數組,編寫一個函數來計算它們的交集。數組
輸入: nums1 = [1,2,2,1], nums2 = [2,2] 輸出: [2,2]bash
$nums1 = [1,2,2,1];
$nums2 = [2,2];
$map = new map\BSTMap();
foreach ($nums1 as $n) {
if ($map->contains($n))
$map->set($n, $map->get($n) + 1);
else
$map->add($n, 1);
}
$arr = [];
foreach ($nums2 as $n) {
if ($map->contains($n)) {
$arr[] = $n;
$map->set($n, $map->get($n) - 1);
if ($map->get($n) == 0)
$map->remove($n);
}
}
複製代碼