给出一个整数数组,堆化操作就是把它变成一个最小堆数组。
对于堆数组A,A[0]是堆的根,并对于每个A[i],A [i * 2 + 1]是A[i]的左儿子并且A[i * 2 + 2]是A[i]的右儿子。
样例
给出 [3,2,1,4,5]
,返回[1,2,3,4,5]
或者任何一个合法的堆数组
挑战
O(n)的时间复杂度完成堆化
说明
什么是堆?
- 堆是一种数据结构,它通常有三种方法:push, pop 和 top。其中,“push”添加新的元素进入堆,“pop”删除堆中最小/最大元素,“top”返回堆中最小/最大元素。
什么是堆化?
- 把一个无序整数数组变成一个堆数组。如果是最小堆,每个元素A[i],我们将得到A[i * 2 + 1] >= A[i]和A[i * 2 + 2] >= A[i]
如果有很多种堆化的结果?
- 返回其中任何一个。
解题思路:
首先将数组看作是一个完全二叉树结构,需要寻找到最后一个非叶子节点(即最后叶子节点的父节点),从此节点向前遍历,依次进行SiftDown操作
public class Solution {
/*
* @param A: Given an integer array
* @return: nothing
*/
public void heapify(int[] A) {
// 从最后一个非叶子节点向前遍历,依次SiftDown
for(int i=(A.length-1)/2; i>=0; i--){
SiftDown(A, i);
}
}
private void SiftDown(int[] A, int k){
while (k < A.length) {
int smallest = k;
//寻找子节点的最小值的索引
if (k * 2 + 1 < A.length && A[k * 2 + 1] < A[smallest])
smallest = k * 2 + 1;
if (k * 2 + 2 < A.length && A[k * 2 + 2] < A[smallest])
smallest = k * 2 + 2;
//如果最小值索引依旧是原索引,说明满足堆的性质,跳出循环
if (smallest == k)
break;
//否则交换k节点与最小索引的节点
swap(A, k, smallest);
//将交换后的子节点继续SiftDown
k = smallest;
}
}
private void swap(int[] A, int i, int j){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}