优先队列/双端队列
1.知识点
- 树:
Linked List 就是特殊化的 Tree
Tree 就是特殊化的 Graph
特点:
二叉搜索树(英语:Binary Search Tree),也称二叉搜索树、有
序二叉树(英语:ordered binary tree),排序二叉树(英语:
sorted binary tree),是指⼀一棵空树或者具有下列列性质的二叉树:
1. 若任意节点的左⼦子树不不空,则左⼦子树上所有结点的值均小于它的根结点的值;
2. 若任意节点的右⼦子树不不空,则右⼦子树上所有结点的值均⼤大于它的根结点的值;
3. 任意节点的左、右⼦子树也分别为⼆二叉查找树。
-
python 定义二叉树
eg:
-
sort list with key
2 代码实战
实战题⽬目
1. https://leetcode.com/problems/validate-binary-search-tree
2. https://leetcode.com/problems/lowest-common-ancestorof-
a-binary-search-tree/
3. https://leetcode.com/problems/lowest-common-ancestorof-
a-binary-tree/
2.1 Validate Binary Search Tree
98. Validate Binary Search Tree
- 方法一(python判重、排序):较低效
class Solution:
def isValidBST(self, root):
inorder = self.inorder(root)
print("中序遍历:{}".format(inorder))
print("排序:{}".format(list(sorted(set(inorder)))))
return inorder == list(sorted(set(inorder)))
def inorder(self,root):
if root is None:
return []
return self.inorder(root.left) + [root.value] + self.inorder(root.right)
class Node:
def __init__(self,value=None,left=None,right=None):
self.value=value
self.left=left #左子树
self.right=right #右子树
root1=Node('D',Node('B',Node('A'),Node('C')),Node('E',right=Node('G',Node('Y'))))
root2=Node('D',Node('B',Node('A'),Node('C')),Node('E',right=Node('G',Node('F'))))
solu = Solution()
solu.isValidBST(root1)
结果:
中序遍历:['A', 'B', 'C', 'D', 'E', 'Y', 'G']
排序:['A', 'B', 'C', 'D', 'E', 'G', 'Y']
False
-前继节点法:节省内存
2.2 Kth Largest Element in a Stream
703. Kth Largest Element in a Stream
利用优先队列中,最小堆的算法,可将时间复杂度降低。上图所示,k*log(k)是快排的时间复杂度,log(2)k是Min Heap的时间复杂度。
C++代码:
class KthLargest {
public:
KthLargest(int k, vector<int>& nums) {
int i;
kth = k;
//将arr中前k个数据放入优先队列中,排序,最小的数在队头
for ( i = 0; i < k && i < nums.size(); i++ )
q.push(nums[i]);
//维护具有k个元素的小顶堆.
while(i < nums.size()) {
if (nums[i] > q.top() ) {
q.pop();
q.push(nums[i]);
}
i++;
}
}
int add(int val) {
int k;
//如果堆为空或者堆长小于k,则继续向堆中加入数据
if (q.empty() || q.size() < kth ) {
q.push(val);
} else {
k = q.top(); //找到堆顶元素,即堆中最小的数
if (val > k ) { //和实时传来的数做比较,维护小顶堆
q.pop();
q.push(val);
}
}
return q.top(); //如果传过来的数比推顶的数小,则舍弃,返回原堆顶的数即可
}
private :
priority_queue<int,vector<int>,greater<int>> q;
int kth;
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
2.3 Sliding Window Maximum
239. Sliding Window Maximum
此题中,不用优先队列。因为窗口中只要维护最大值即可,不用维护第二大,第三大的值,所以算法可以加速,采用双端队列的方法。
维护队列左边最大。
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
//判断输入是否合法
if not nums : return []
//初始化window和存放结果的列表
window, res = [], []
for i, x in enumerate(nums):
//维护窗口大小为k
if i >= k and window[0] <= i - k:
window.pop(0)
//将左侧比当前x值小的数据索引都清掉,维护左端最大
while window and nums[window[-1]] <= x:
window.pop()
window.append(i)
//将最大值放入res列表中
if i >= k-1:
res.append(nums[window[0]])
return res