// arr[index]位置的数,往下移动 publicstaticvoidheapify(int[] arr, int index, int heapSize){ int left = index * 2 + 1; // 左孩子的下标 while (left < heapSize) { // 下方还有孩子的时候 // 两个孩子中,谁的值大,把下标给largest // 1) 只有左孩子,left -> largest // 2) 同时有左孩子和右孩子,右孩子的值 <= 左孩子的值,left -> largest // 3) 同时有左孩子和右孩子并且右孩子的值 > 左孩子的值, right -> largest int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left; // 父和较大的孩子之间,谁的值大,把下标给largest largest = arr[largest] > arr[index] ? largest : index; if (largest == index) { break; } swap(arr, largest, index); index = largest; left = index * 2 + 1; } }
publicstaticvoidswap(int[] arr, int i, int j){ int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
// O(N*logK) publicstaticvoidsortedArrDistanceLessK(int[] arr, int k){ if (k == 0) { return; } // 默认小根堆 PriorityQueue<Integer> heap = new PriorityQueue<>(); int index = 0; // 0...K-1 for (; index <= Math.min(arr.length - 1, k - 1); index++) { heap.add(arr[index]); } int i = 0; for (; index < arr.length; i++, index++) { heap.add(arr[index]); arr[i] = heap.poll(); } while (!heap.isEmpty()) { arr[i++] = heap.poll(); } }
// 暴力方法 O((max - min) * N) publicstaticintmaxCover1(int[][] lines){ int min = Integer.MAX_VALUE; // 所有线段最小值 int max = Integer.MIN_VALUE; // 所有线段最大值 for (int i = 0; i < lines.length; i++) { min = Math.min(min, lines[i][0]); max = Math.max(max, lines[i][1]); } int cover = 0; for (double p = min + 0.5; p < max; p += 1) { // 每0.5统计在范围内的线段数 int cur = 0; // 包含当前0.5的线段数 for (int i = 0; i < lines.length; i++) { if (lines[i][0] < p && lines[i][1] > p) { cur++; } } cover = Math.max(cover, cur); // 重合最多的0.5对应的线段数量 } return cover; }
// 堆实现 O(N*logN) publicstaticintmaxCover2(int[][] m){ // 先按照线段左位置start排序 Arrays.sort(m, (a, b) -> (a[0] - b[0])); // 准备好小根堆 PriorityQueue<Integer> heap = new PriorityQueue<>(); int max = 0; for (int[] line : m) { while (!heap.isEmpty() && heap.peek() <= line[0]) { heap.poll(); // 弹出所有小于start的数 } heap.add(line[1]); // end加入小根堆 max = Math.max(max, heap.size()); // 小根堆里剩下的是跟当前线段重合的线段数量 } return max; }