Lintcode: Heapify && Summary: Heap
Given an integer array, heapify it into a min-heap array.
For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] and A[i * 2 + 2] is the right child of A[i].
Example
Given [3,2,1,4,5], return [1,2,3,4,5] or any legal heap array. Challenge
O(n) time complexity Clarification
What is heap? Heap is a data structure, which usually have three methods: push, pop and top. where "push" add a new element the heap, "pop" delete the minimum/maximum element in the heap, "top" return the minimum/maximum element. What is heapify?
Convert an unordered integer array into a heap array. If it is min-heap, for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i]. What if there is a lot of solutions?
Return any of them.
Heap的介绍1,介绍2,要注意complete tree和full tree的区别, Heap是complete tree;Heap里面 i 的 children分别是 i*2+1 和 i*2+2,i 的 parent是 (i-1)/2
Heapify的基本思路就是:Given an array of N values, a heap containing those values can be built by simply “sifting” each internal node down to its proper location:
1. start with the last internal node
2. swap the current internal node with its smaller child, if necessary
3. then follow the swapped node down
4. continue until all internal nodes are done
public class Solution {
/**
* @param A: Given an integer array
* @return: void
*/
public void heapify(int[] A) {
int start = A.length/2;
for (int i=start;i>=0;i--)
shiftDown(i, A);
} private void shiftDown(int ind, int[] A){
int size = A.length;
int left = ind*2+1;
int right = ind*2+2;
while (left<size || right<size){
int leftVal = (left<size) ? A[left] : Integer.MAX_VALUE;
int rightVal = (right<size) ? A[right] : Integer.MAX_VALUE;
int next = (leftVal<=rightVal) ? left : right;
if (A[ind]<A[next]) break;
else {
swap(A, ind,next);
ind = next;
left = ind*2+1;
right = ind*2+2;
}
}
} private void swap(int[] A, int x, int y){
int temp = A[x];
A[x] = A[y];
A[y] = temp;
}
}
注意第7行,start之所以从A.length/2开始,是因为要从Internal node开始,除开最后一行。其实可以写成start = (A.length - 1 - 1) / 2, 求最后一个index的parent index的基本做法。
17-18行的技巧,不存在就补齐一个很大的数,因为反正最终是求小的,这样省了很多行分情况讨论
下面给出Heap的 Summary, 转来的:implemented a Heap class that can specify min heap or max heap with insert, delete root and build heap functions.
Time Complexity分析:Binary Heap
Java PriorityQueue (Java Doc) time complexity for 1 operation
O(log n) time for the enqueing and dequeing methods (offer, poll, remove() and add). Note that this remove() is inherited, it's not remove(object). This retrieves and removes the head of this queue.
O(n) for the remove(Object) and contains(Object) methods
O(1) for the retrieval methods (peek, element, and size)
The insertion/poll of n elements should be O(n log n)
Build本来应该O(NlogN), 但是如果用巧妙办法:The optimal method starts by arbitrarily putting the elements on a binary tree, respecting the shape property (the tree could be represented by an array, see below). Then starting from the lowest level and moving upwards, shift the root of each subtree downward as in the deletion algorithm until the heap property is restored. 时间复杂度是 O(N)., 参看上面链接里面build a Heap部分证明
These time complexities seem all worst case (wiki), except for .add()
. You are right to question the bounds as the Java Doc also states to the extension of this unbound structure:
The details of the growth policy are not specified
As they state in the Doc as well, the PriorityQueue is based on an array with a specific initial capacity. I would assume that the growth will cost O(n) time, which then would also be the worst case time complexity for .add()
.
To get a guaranteed O(n log n) time for adding n elements you may state the size of your n elements to omit extension of the container: PriorityQueue(int initialCapacity)
Priority Queue work with Map.Entry
some syntax: everytime you change the Map.Entry, you should take it out and put it into PQ again in order for it to be sorted.
If you just change the value of the undelying Map.Entry, PQ won't sort by itself. Example: https://www.cnblogs.com/EdwardLiu/p/11738048.html
class Heap{
private int[] nodes;
private int size;
private boolean isMaxHeap; public Heap(int capa, boolean isMax){
nodes = new int[capa];
size = 0;
isMaxHeap = isMax;
} //Build heap from given array.
public Heap(int[] A, boolean isMax){
nodes = new int[A.length];
size = A.length;
isMaxHeap = isMax;
for (int i=0;i<A.length;i++) nodes[i] = A[i];
int start = A.length/2;
for (int i=start;i>=0;i--)
shiftDown(i);
} //Assume A and nodes have the same length.
public void getNodesValue(int[] A){
for (int i=0;i<nodes.length;i++) A[i] = nodes[i];
} public boolean isEmpty(){
if (size==0) return true;
else return false;
} public int getHeapRootValue(){
//should throw exception when size==0;
return nodes[0];
} private void swap(int x, int y){
int temp = nodes[x];
nodes[x] = nodes[y];
nodes[y] = temp;
} public boolean insert(int val){
if (size==nodes.length) return false;
size++;
nodes[size-1]=val;
//check its father iteratively.
int cur = size-1;
int father = (cur-1)/2;
while (father>=0 && ((isMaxHeap && nodes[cur]>nodes[father]) || (!isMaxHeap && nodes[cur]<nodes[father]))){
swap(cur,father);
cur = father;
father = (cur-1)/2;
}
return true;
} private void shiftDown(int ind){
int left = (ind+1)*2-1;
int right = (ind+1)*2;
while (left<size || right<size){
if (isMaxHeap){
int leftVal = (left<size) ? nodes[left] : Integer.MIN_VALUE;
int rightVal = (right<size) ? nodes[right] : Integer.MIN_VALUE;
int next = (leftVal>=rightVal) ? left : right;
if (nodes[ind]>nodes[next]) break;
else {
swap(ind,next);
ind = next;
left = (ind+1)*2-1;
right = (ind+1)*2;
}
} else {
int leftVal = (left<size) ? nodes[left] : Integer.MAX_VALUE;
int rightVal = (right<size) ? nodes[right] : Integer.MAX_VALUE;
int next = (leftVal<=rightVal) ? left : right;
if (nodes[ind]<nodes[next]) break;
else {
swap(ind,next);
ind = next;
left = (ind+1)*2-1;
right = (ind+1)*2;
}
}
}
} public int popHeapRoot(){
//should throw exception, when heap is empty. int rootVal = nodes[0];
swap(0,size-1);
size--;
if (size>0) shiftDown(0);
return rootVal;
}
} public class Solution {
/**
* @param A: Given an integer array
* @return: void
*/
public void heapify(int[] A) {
if (A.length==0) return; Heap minHeap = new Heap(A,false);
minHeap.getNodesValue(A);
}
}
经常有关Heap的问题比如:
k largest(or smallest) elements in an array
Write an efficient program for printing k largest elements in an array. Elements in array can be in any order.
常用的方法肯定有QuickSelect, 用Heap也有两种方法可解:
Method Use Max Heap
1) Build a Max Heap tree in O(n)
2) Use Extract Max k times to get k maximum elements from the Max Heap O(klogn)
这个Max Heap的size是O(N)
Time complexity: O(n + klogn)
推荐方法:
Method Use Min Heap
1) Build a Min Heap MH of the first k elements (arr[0] to arr[k-1]) of the given array. O(k)
2) For each element, after the kth element (arr[k] to arr[n-1]), compare it with root of MH.
a) If the element is greater than the root then make it root and call heapifyfor MH
b) Else ignore it.
// The step 2 is O((n-k)*logk)
3) Finally, MH has k largest elements and root of the MH is the kth largest element.
这个Min Heap的size是O(k)
Time Complexity: O(k + (n-k)Logk) without sorted output.
Lintcode: Heapify && Summary: Heap的更多相关文章
- LintCode "Heapify"
My first try was, using partial sort to figure out numbers layer by layer in the heap.. it only fail ...
- Lintcode: Singleton && Summary: Synchronization and OOD
Singleton is a most widely used design pattern. If a class has and only has one instance at every mo ...
- 算法 Heap sort
// ------------------------------------------------------------------------------------------------- ...
- Python常用数据结构之heapq模块
Python数据结构常用模块:collections.heapq.operator.itertools heapq 堆是一种特殊的树形结构,通常我们所说的堆的数据结构指的是完全二叉树,并且根节点的值小 ...
- linux调试工具glibc的演示分析-core dump double free【转】
转自:http://www.cnblogs.com/jiayy/p/3475544.html 偶然中发现,下面的两端代码表现不一样 void main(){ void* p1 = malloc(32) ...
- linux调试工具glibc的演示分析
偶然中发现,下面的两端代码表现不一样 void main(){ void* p1 = malloc(32); free(p1); free(p1); // 这里会报double free ...
- Windbg基本命令应用总结
.cordll -ve -u -l //reload core dlls ------加载下载系统文件符号的URL---------- .sympath SRV*C:\Symbols*http://m ...
- centos安装hadoop(伪分布式)
在本机上装的CentOS 5.5 虚拟机, 软件准备:jdk 1.6 U26 hadoop:hadoop-0.20.203.tar.gz ssh检查配置 [root@localhost ~]# ssh ...
- [算法]打印N个数组的整体最大Top K
题目: 有N个长度不一的数组,所有的数组都是有序的,请从大到小打印这N个数组整体最大的前K个数. 例如: 输入含有N行元素的二维数组代表N个一维数组. 219,405,538,845,971 148, ...
随机推荐
- 高性能Android应用开发
- ARC下带CF前缀的类型与OC类型转换
在对钥匙串操作时这个函数 OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_R ...
- 关于 ArrayList.toArray() 和 Arrays.asList().toArray()方法
1.ArrayList.toArray() 理解 * 通过源码我们可以看到返回的是Object类型的数组,失去了原有的实际类型,虽然底层存储是具体类型的对象,这也正体现了文档中说的:该方法起到了 ...
- 题目1461:Tempter of the bone(深度优先遍历DFS)
题目链接:http://ac.jobdu.com/problem.php?pid=1461 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- redmine创建新闻,自动发邮件给项目组所有成员
redmine创建新闻,自动发邮件给项目组所有成员: 1.添加用户至公共项目内 2.配置系统邮件推送配置 3.检查用户接受推送配置 3.使用管理员账户发布新闻(不能自己发送自己) 4.查看邮件接受邮件
- python3查询数据库并生成excel报表
#!/usr/bin/env python3 #encoding=UTF- import os import time import xlwt hostIp = 'xxx.xxx.xxx.xx' us ...
- Spring JPA配置讲解
JPA是Java EE5规范之一,是一个orm规范,由厂商来实现该规范.目前有hibernate,OpenJPA,TopLink和EclipseJPA等实现 Spring提供三种方法集成JPA: 1. ...
- Vim 使用入门快捷键
Vim 和 Emac 都是利器啊,前段时间决定熟悉一套跨平台的编辑器,以便在 Win,Mac,Ubuntu 下都有相同的编辑体验. 于是尝试了一下 Vim,使用了一段时间,确实比 UE 之类的要高效. ...
- 那些你觉得堪称神兵利器的 Chrome 插件
子曾曰:"工欲善其事,必先利其器.居是邦也."--语出<论语·卫灵公>:其后一百多年,荀子也在其<劝学>中倡言道:"吾尝终日而思矣,不如须臾之所学 ...
- 单例模式:Qt本身就提供了专门的宏 Q_GLOBAL_STATIC 通过这个宏不但定义简单,还可以获得线程安全性
标题起的是有点大 主要是工作和学习中,遇到些朋友,怎么说呢,代码不够Qt化 可能是由于他们一开始接触的是 Java MFC 吧 接触 Qt 7个年头了 希望我的系列文章能抛砖引玉吧 单例模式 很多人洋 ...