Data Structure -Heap

363. Trapping Rain Water

双指针

https://www.lintcode.com/problem/trapping-rain-water/description

思路:每个点可盛的水是左右两边最大值中的最小值-当前点的值

 1 public class Solution {
 2     /**
 3      * @param heights: a list of integers
 4      * @return: a integer
 5      */
 6     public int trapRainWater(int[] heights) {
 7         // write your code here
 8         if(heights==null || heights.length==0){
 9             return 0;
10         }
11         
12         int left = 0;
13         int right = heights.length-1;
14         
15         int sum = 0;
16         int maxLeft = Integer.MIN_VALUE;
17         int maxRight =Integer.MIN_VALUE;
18         while(left<right){
19             maxLeft = Math.max(heights[left],maxLeft);
20             maxRight = Math.max(heights[right],maxRight);
21             
22             if(maxRight>maxLeft){
23                 sum +=maxLeft-heights[left];
24                 left++;
25             }else{
26                 sum+=maxRight-heights[right];
27                 right--;
28             }
29         }
30         return sum;
31     }
32 }
View Code

 

364. Trapping Rain Water II

https://www.lintcode.com/problem/trapping-rain-water-ii/description?_from=ladder&&fromId=4

思路:heap

循环取出最小堆堆顶,若最小值周围有更小值,说明改处可积水,那么更新sum,并将该值赋值为刚取出的堆顶值,继续将周围一圈值加入堆

class Point {
    int x;
    int y;
    int height;

    public Point(int x, int y, int height) {
        this.x = x;
        this.y = y;
        this.height = height;
    }
}

public class Solution {
    /**
     * @param heights: a matrix of integers
     * @return: an integer
     */
    int[] dx = {0, 1, 0, -1};
    int[] dy = {1, 0, -1, 0};
    public int trapRainWater(int[][] heights) {
        // write your code here
        if (heights == null || heights.length == 0 || heights[0].length == 0) {
            return 0;
        }
        int r = heights.length;
        int c = heights[0].length;
        boolean[][] visited = new boolean[r][c];

        Comparator<Point> minComparator = new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return o1.height - o2.height;
            }
        };

        PriorityQueue<Point> minHeap = new PriorityQueue<>(minComparator);
        
        //将周围四条边加入最小堆
        for(int i=0;i<r;i++){
            minHeap.add(new Point(i,0,heights[i][0]));
            visited[i][0] = true;
            minHeap.add(new Point(i, c - 1, heights[i][c - 1]));
            visited[i][c - 1] = true;
        }
        
        for (int j = 0; j < c; j++) {
            minHeap.add(new Point(0, j, heights[0][j]));
            visited[0][j] = true;
            minHeap.add(new Point(r - 1, j, heights[r - 1][j]));
            visited[r - 1][j] = true;
        }
        
        
        //循环取出最小堆堆顶,若最小值周围有更小值,说明改处可积水
        //那么更新sum,并将该值赋值为刚取出的堆顶值
        //继续将周围一圈值加入堆
        int sum =0;
        while(!minHeap.isEmpty()){
            Point point = minHeap.poll();
            
            for(int i =0;i<4;i++){
                int nx = point.x+dx[i];
                int ny = point.y+dy[i];
                
                if(!isValid(nx,ny,heights,visited)){
                    continue;
                }
                
                visited[nx][ny]=true;
                
                if(heights[nx][ny]<point.height){
                    sum+=point.height-heights[nx][ny];
                    heights[nx][ny]= point.height;
                }
                
                minHeap.add(new Point(nx,ny,heights[nx][ny]));
            }
        }
        
        return sum;

    }
    
    public boolean isValid(int x, int y, int[][] heights, boolean[][] visited) {
        if (x < 0 || x > heights.length - 1 || y < 0 || y > heights[0].length - 1) {
            return false;
        }
        if (visited[x][y]) {
            return false;
        }
        return true;
    }
}
View Code

 

360. Sliding Window Median

https://www.lintcode.com/problem/sliding-window-median/description?_from=ladder&&fromId=4

思路:heap

priorityQueue remove操作是O(N) treeset是O(logN) 此题用treeset

class Node implements Comparable<Node>{
    int id;
    int val;
    Node(int id, int val) {
        this.id = id;
        this.val = val;
    }
    public int compareTo(Node other){
        Node a = (Node)other;
        if(this.val == a.val){
            return this.id - a.id;
        }
        return this.val-a.val;
    }
}

public class Solution {
    /**
     * @param nums: A list of integers
     * @param k: An integer
     * @return: The median of the element inside the window at each moving
     */
    public List<Integer> medianSlidingWindow(int[] nums, int k) {
        // write your code here
        int n = nums.length;
        TreeSet<Node> minheap = new TreeSet<Node>();
        TreeSet<Node> maxheap = new TreeSet<Node>();
        ArrayList<Integer> result = new ArrayList<Integer> ();
        
        if (k == 0)
            return result;
        
        int half = (k+1)/2;
        for(int i=0; i<k-1; i++) {
            add(minheap, maxheap, half, new Node(i, nums[i]));
        }
        for(int i=k-1; i<n; i++) {
            add(minheap, maxheap, half, new Node(i, nums[i]));
            result.add(minheap.last().val);
            remove(minheap,maxheap, new Node(i-k+1, nums[i-k+1]));
        }
        return result;
    }
    
    void add(TreeSet<Node> minheap,TreeSet<Node> maxheap, int size,Node node){
       if (minheap.size()<size) {
            minheap.add(node);
        }
        else {
            maxheap.add(node);
        }
        if (minheap.size()==size) {
            if (maxheap.size()>0 && minheap.last().val>maxheap.first().val) {
                Node s = minheap.last();
                Node b = maxheap.first();
                minheap.remove(s);
                maxheap.remove(b);
                minheap.add(b);
                maxheap.add(s);
            }
        }
    }
    
    void remove(TreeSet<Node>minheap, TreeSet<Node> maxheap, Node node) {
        if (minheap.contains(node)) {
            minheap.remove(node);
        }
        else {
            maxheap.remove(node);
        }
    }
}
View Code

 

转载于:https://www.cnblogs.com/lizzyluvcoding/p/10772172.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值