heap堆 -> Priority Queue优先级队列
数组实现完全二叉树
拥有的性质:
任意节点的左孩子: 2 * i + 1
右孩子: 2 * i + 2
父节点: (i - 1) / 2
大根堆: 父节点比子节点大(并不一定是完全有序)
时间复杂度: O(N * log N)
不多废话,代码实现堆排序 :
public static void heapSort(int[] arr) {
if(arr == null || arr.length < 2) {
return;
}
// 这步可以满足数组一个值一个值赋予
// for(int i = 0; i < arr.length; i++) {
// heapInsert(arr, i);
// }
//这步只能适用于一起给一堆数据排序
for(int i = arr.length - 1; i >= 0; i--) {
heapify(arr, i, arr.length);
}
int heapSize = arr.length;
swap(arr, 0, --heapSize);
while(heapSize > 0) {
heapify(arr, 0, heapSize);
swap(arr, 0, --heapSize);
}
}
//二叉树由下向上升
private void heapInsert(int[] arr, int index) {
while(arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
//二叉树由顶向下降
private void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 1;
while(left < heapSize) {
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
largest = arr[largest] > arr[index] ? largest : index;
if(largest == index) {
break;
}
swap(arr, largest, index);
index = largest;
left = index * 2 + 1;
}
}
private void swap(int[] arr, int i , int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
使用堆解决的题:
最大线段重合问题
public static class Line {
public int start;
public int end;
public Line(int s, int e) {
start = s;
end = e;
}
}
public static class StartComparator implements Comparator<Line> {
@Override
public int compare(Line o1, Line o2) {
return o1.start - o2.start;
}
}
public static int maxCover(int[][] m) {
Line[] lines = new Line[m.length];
//把数组用类封装,才能用Arrays.sort方法排序
for(int i = 0; i < m.length; i++) {
lines[i] = new Line(m[i][0], m[i][1]);
}
Arrays.sort(lines, new StartComparator());
//优先级队列默认小根堆
PriorityQueue<Integer> heap = new PriorityQueue<>();
int max = 0;
for(int i = 0; i < lines.length; i++) {
while(!heap.isEmpty() && heap.peek() <= lines[i].start) {
heap.poll();
}
heap.add(lines[i].end);
max = Math.max(max, heap.size());
}
return max;
}