Heap

相关Java知识

1. 新建堆 默认是最小堆
PriorityQueue操作时间复杂度: 
add: O(logn); 
heap本身支持O(logn)的remove 但是PriorityQueue的remove是O(n); 
pop: O(logn)
peek: O(1) 
Queue heap = new PriorityQueue<>();

2. 自定义排序规则 下例是ListNode的最小堆
private Comparator ListNodeComparator = new Comparator(){
        public int compare(ListNode left, ListNode right){
            return left.val-right.val;
        }
};
Queue heap = new PriorityQueue<>(lists.length, ListNodeComparator);

3. 也可以implements Comparable接口
Queue minHeap = new PriorityQueue();
class Point implements Comparable{
        int x;
        int y;
        int val;
        Point(int x, int y, int val){
            this.x = x;
            this.y = y;
            this.val = val;
        }
        @Override
        public int compareTo(Point b){
            return this.val-b.val;
        }
    }
4. 如果不是自定义类型的话 可以直接这样建最大堆
maxHeap = new PriorityQueue(Collections.reverseOrder());

题目

  1. 264 Ugly Number II 两种方法:用堆O(nlogn)/利用丑数的特性一个一个算出来O(n)
  2. 263 Ugly Number
  3. 23 Merge k Sorted Lists 三种做法 heap merge divideconque 都是O(N*logk) N是所有元素总数 k是lists总数

topK类问题
topK两种思路:
1 离线算法 用quick select O(n)时间选出第k大的数 然后在O(n)时间扫描一下把小于这个数的所有数选出来 总时间复杂度O(n) 如果排序就O(n)+O(klogk)
2 在线算法 用max heap O(nlogn+klogn); 更好的方法是用min heap O(nlogk)
找大的就用最小堆 每次剔除最小的; 找最近的就用最大堆 每次剔除最近的
第k大的

  1. 703 Kth Largest in a Stream(online) 215 Kth Largest in an Array(offline)
    前k大的
  2. 545 Top k Largest Numbers II(online) 544 Top k Largest Numbers(offline) (详见双指针quick sort篇)
  3. 前k近的 658 Find K Closest Elements
  • 用maxheap O(nlogk)
  • 因为是找距离target最近的k个 所以可以排序 然后binarysearch到第一个比target小的位置 然后左右双指针一一添加 排序O(nlogn) + binarySearch O(logn) + 找k个 k
  1. 613 High Five
  • 给一个Record数组(id score) 返回每个学生最高5个分数的平均分 为每个学生建一个堆
  1. 295 Find Median from Data Stream
  • 挺有意思的这个题 建两个堆minHeap maxHeap,维持minHeap中元素都大于等于maxHeap中的元素,且元素差小于二 logn to insert, O(1) to query
  1. 378 Kth Smallest Element in a Sorted Matrix
  • heap 一行或者一列扔进堆 取出一个然后把同列或同行的下一个扔进去 k(logk)
  • 二分法
  1. 373 Find K Pairs with Smallest Sums

264. Ugly Number II

class Solution {
    public int nthUglyNumber(int n) {
        return nMethod(n);
        return nlognMethod(n);
    }
    public int nlognMethod(int n) {
        Queue heap = new PriorityQueue<>();
        Set set = new HashSet<>();
        heap.add(1);
        set.add(1);
        int[] ugly = {2, 3, 5};
        while(n>1){
            int top = heap.poll();
            for(int i=0; i<3; i++){
                int next = top*ugly[i];
                if(next/ugly[i]!=top)
                    continue;
                if(!set.contains(next)){
                    set.add(next);
                    heap.offer(next);
                } 
            }
            n = n-1;
        }
        return heap.peek();
    }
    public int nMethod(int n) {
        int[] ugly = new int[n];
        ugly[0] = 1;
        int index2 = 0, index3 = 0, index5 = 0;
        int factor2 = 2, factor3 = 3, factor5 = 5;
        for(int i=1;i

263 Ugly Number

class Solution {
    public boolean isUgly(int num) {
        if(num==0)
            return false;
        while(num%2==0)
            num = num/2;
        while(num%3==0)
            num = num/3;
        while(num%5==0)
            num = num/5;
        return num==1;
    }
}

23 Merge k Sorted Lists 三种做法 heap merge divideconque

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    private Comparator ListNodeComparator = new Comparator(){
        public int compare(ListNode left, ListNode right){
            return left.val-right.val;
        }
    };
    public ListNode mergeKLists(ListNode[] lists) {
        return heapMethod(lists);
        // return mergeMethod(lists);
    }
    
    private ListNode heapMethod(ListNode[] lists){
        if(lists==null || lists.length==0)
            return null;
        Queue heap = new PriorityQueue<>(lists.length, ListNodeComparator);
        for(int i=0; i=end)
            return lists[start];
        int mid = start+(end-start)/2;
        ListNode left = mergelist(lists, start, mid);
        ListNode right = mergelist(lists, mid+1, end);
        return merge(left, right);
    }
    
    private ListNode merge(ListNode left, ListNode right){
        ListNode dummy = new ListNode(0);
        ListNode node = dummy;
        while(left!=null && right!=null){
            if(left.val<=right.val){
                node.next = left;
                left=left.next;
                node = node.next;
            }else{
                node.next = right;
                right = right.next;
                node = node.next;
            }
        }
        while(left!=null){
            node.next = left;
            left = left.next;
            node = node.next;
        }
        while(right!=null){
            node.next = right;
            right = right.next;
            node = node.next;
        }
        return dummy.next;
    }
}

703. Kth Largest Element in a Stream

class KthLargest {
    Queue heap;
    int k;
    public KthLargest(int k, int[] nums) {
        heap = new PriorityQueue<>(k);
        this.k = k;
        for(int i=0; ik)
                heap.poll();
        }
    }
    
    public int add(int val) {
        heap.offer(val);
        if(heap.size()>k)
            heap.poll();
        return heap.peek();
    }
}

215. Kth Largest Element in an Array

  • quickselect O(n)
  • heap O(nlogK)
class Solution {
    public int findKthLargest(int[] nums, int k) {
        // return heap(nums, k);
        return partition(nums, k);
    }
    public int heap(int[] nums, int k) {
        if(nums==null || k<=0 || nums.length heap = new PriorityQueue<>(k);
        for(int i=0; i=end)
            return nums[start];
        int left = start;
        int right = end;
        int mid = left+(right-left)/2;
        int pivot = nums[mid];
        while(left<=right){
            while(left<=right && nums[left]>pivot){
                left++;
            }
            while(left<=right && nums[right]=left-start+1)
            return helper(nums, k-(left-start), left, end);
        return nums[right+1];
    }
}

545. Top k Largest Numbers II

public class Solution {
    Queue heap;
    int k;
    /*
    * @param k: An integer
    */public Solution(int k) {
        // do intialization if necessary
        heap = new PriorityQueue<>(k);
        this.k = k;
    }

    /*
     * @param num: Number to be added
     * @return: nothing
     */
    public void add(int num) {
        // write your code here
        heap.offer(num);
        if(heap.size()>k)
            heap.poll();
    }

    /*
     * @return: Top k element
     */
    public List topk() {
        // write your code here
        List result = new ArrayList<>();
        Iterator it = heap.iterator();
        while(it.hasNext()){
            result.add((Integer)it.next());
        }
        Collections.sort(result, Collections.reverseOrder());
        return result;
    }
}

544. Top k Largest Numbers

public class Solution {
    /**
     * @param nums: an integer array
     * @param k: An integer
     * @return: the top k largest numbers in array
     */
    public int[] topk(int[] nums, int k) {
        // write your code here
        int kth = findKthLargest(nums, k, 0, nums.length-1);
        int[] result = new int[k];
        int left=0;
        int right = k-1;
        System.out.println(kth);
        for(int i=0; ikth){
                result[left] = nums[i];
                left++;
            }
            if(nums[i]==kth&&right>=left){
                result[right] = nums[i];
                right--;
            }
        }
        Arrays.sort(result);
        int start = 0;
        int end = k-1;
        while(start=end)
            return nums[start];
        int mid = start + (end-start)/2;
        int pivot = nums[mid];
        int left = start;
        int right = end;
        while(left<=right){
            while(left<=right && nums[left]>pivot){
                left++;
            }
            while(left<=right && nums[right]=left)
            return findKthLargest(nums, k-(left-start), left, end);
        return nums[right+1];
    }
}

// base on heap
class Solution {
    /*
     * @param nums an integer array
     * @param k an integer
     * @return the top k largest numbers in array
     */
     public int[] topk(int[] nums, int k) {
         PriorityQueue minheap = new PriorityQueue(k, new Comparator() {
             public int compare(Integer o1, Integer o2) {
                 return o1 - o2;
             }
         });

         for (int i : nums) {
             minheap.add(i);
             if (minheap.size() > k) {
                minheap.poll();
             }
         }

         int[] result = new int[k];
         for (int i = 0; i < result.length; i++) {
             result[k - i - 1] = minheap.poll();
         }
         return result;
    }
};

// base on quicksort
import java.util.Random;

class Solution {
    /*
     * @param nums an integer array
     * @param k an integer
     * @return the top k largest numbers in array
     */
    public int[] topk(int[] nums, int k) {
        // Write your code here
        quickSort(nums, 0, nums.length - 1, k);

        int[] topk = new int[k];
        for (int i = 0; i < k; ++i)
            topk[i] = nums[i];

        return topk;
    }
    
    private void quickSort(int[] A, int start, int end, int k) {
        if (start >= k)
            return;

        if (start >= end) {
            return;
        }
        
        int left = start, right = end;
        // key point 1: pivot is the value, not the index
        Random rand =new Random(end - start + 1);
        int index = rand.nextInt(end - start + 1) + start;
        int pivot = A[index];

        // key point 2: every time you compare left & right, it should be 
        // left <= right not left < right
        while (left <= right) {
            // key point 3: A[left] < pivot not A[left] <= pivot
            while (left <= right && A[left] > pivot) {
                left++;
            }
            // key point 3: A[right] > pivot not A[right] >= pivot
            while (left <= right && A[right] < pivot) {
                right--;
            }

            if (left <= right) {
                int temp = A[left];
                A[left] = A[right];
                A[right] = temp;
                
                left++;
                right--;
            }
        }
        
        quickSort(A, start, right, k);
        quickSort(A, left, end, k);
    }
};

658. Find K Closest Elements

class Solution {
    public List findClosestElements(int[] arr, int k, int target) {
        return maxHeap(arr, k, target);
        //return binarySearch(arr, k, target);
    }
    private List maxHeap(int[] arr, int k, int target){
        Queue heap = new PriorityQueue<>(k+1, new Comparator(){
            public int compare(Integer x, Integer y){
                int diff = -Math.abs(x-target)+Math.abs(y-target);
                if(diff!=0)
                    return diff;
                return y-x;
            }
        });
        for(int i=0; ik)
                heap.poll();
        }
        List temp = new ArrayList<>();
        for(int i=0; i binarySearch(int[] arr, int k, int target) {
        List result = new ArrayList<>();
        if(arr==null || arr.length0){
            if(left<0)
                right++;
            else if(right>arr.length-1)
                left--;
            else{
                if(target-arr[left]>arr[right]-target)
                    right++;
                else
                    left--;
            }
            k--;
        }
        for(int i=left+1; i

613 High Five

public class Solution {
    /**
     * @param results a list of 
     * @return find the average of 5 highest scores for each person
     * Map (student_id, average_score)
     */
    public Map highFive(Record[] results) {
        // Write your code here
        Map result = new HashMap<>();
        Map> scoreHeaps = new HashMap<>();
        for(Record record: results){
            int id = record.id;
            int score = record.score;
            PriorityQueue heap = scoreHeaps.getOrDefault(id,new PriorityQueue(5));
            heap.offer(score);
            if(heap.size()>5)
                heap.poll();
            scoreHeaps.put(id, heap);
        }
        for(Integer id : scoreHeaps.keySet()){
            PriorityQueue heap = scoreHeaps.get(id);
            Iterator it = heap.iterator();
            int sum = 0;
            while(it.hasNext()){
                sum = sum+(int)it.next();
            }
            double average = (double) sum/heap.size();
            System.out.println(average);
            result.put(id, average);
        }
        return result;
    }
}
  1. 295 Find Median from Data Stream
    logn to insert, O(1) to query
class MedianFinder {
    Queue minHeap;
    Queue maxHeap;
    /** initialize your data structure here. */
    public MedianFinder() {
        minHeap = new PriorityQueue();
        maxHeap = new PriorityQueue(Collections.reverseOrder());
    }
    
    public void addNum(int num) {
        maxHeap.offer(num);
        minHeap.offer(maxHeap.poll());
        if(minHeap.size()>maxHeap.size()+1)
            maxHeap.offer(minHeap.poll());
    }
    
    public double findMedian() {
        if(minHeap.size()==maxHeap.size())
            return (double)(minHeap.peek()+maxHeap.peek())/2;
        return minHeap.peek();
    }
} 
  1. 378 Kth Smallest Element in a Sorted Matrix
class Solution {
    public int kthSmallest(int[][] matrix, int k) {
        Queue minHeap = new PriorityQueue();
        for(int i=0; i{
        int x;
        int y;
        int val;
        Point(int x, int y, int val){
            this.x = x;
            this.y = y;
            this.val = val;
        }
        @Override
        public int compareTo(Point b){
            return this.val-b.val;
        }
    }
}
  1. 373 Find K Pairs with Smallest Sums

你可能感兴趣的:(Heap)