【Leetcode】算法总结——堆

【Leetcode】算法总结——堆

2. 堆

  1. Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Example:

Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6

解法一: 先算两个链表的合并

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        
		int len=lists.length;
        ListNode  r=null;
        if(len==0){
            return null;
        }
        if(len==1){
            return lists[0];
        }
        if(len==2){
            return mergeTwoLists(lists[0],lists[1]);

        }
        for(int i=2;i<len;i++){
            r=mergeTwoLists(lists[i-1],lists[i-2]);
            r=mergeTwoLists(r,lists[i]);
        }
        return r;
		
        
    }
	private ListNode mergeTwoLists(ListNode node1,ListNode node2) {
		ListNode p=node1;
		ListNode q=node2;
		ListNode pre=null;//p指针的前一个
		if(p==null){
            return node2;
        }
        if(q==null){
            return node1;
        }
		while(p!=null&&q!=null) {
			int val1=p.val;
			int val2=q.val;
			//情况1
			if(val1>val2) {
				if(pre==null) {
					//这种情况是node1的第一个数字node2的第一个数大,需要将node2的第一个数插入到node1的第一个书前面
					node1=q;
					q=q.next;
					node1.next=p;
					pre=node1;
					
				}
				else {
					pre=q;
					q=q.next;
					pre.next=p;
					
			   }
			   		
			}
			else {
				if(p.next==null) {
					//将q插入到p后面
					p.next=q;
					break;
				}
				else {
					int val=p.next.val;
					if(val>=val2) {
						//插进入
						ListNode r=p.next;
						p.next=q;
						q=q.next;
						p.next.next=r;
						pre=p;
						p=p.next;
					}
					else {
						pre=p;
						p=p.next;
						
					}
				}
			}
			
		if(p==null&&q!=null) {
			pre.next=q;
		}
			
		}
		return node1;
		
	}
}

方法二:分治

class Solution {

    public ListNode mergeKLists(ListNode[] lists){
        if(lists.length == 0)
            return null;
        if(lists.length == 1)
            return lists[0];
        if(lists.length == 2){
           return mergeTwoLists(lists[0],lists[1]);
        }

        int mid = lists.length/2;
        ListNode[] l1 = new ListNode[mid];
        for(int i = 0; i < mid; i++){
            l1[i] = lists[i];
        }

        ListNode[] l2 = new ListNode[lists.length-mid];
        for(int i = mid,j=0; i < lists.length; i++,j++){
            l2[j] = lists[i];
        }

        return mergeTwoLists(mergeKLists(l1),mergeKLists(l2));

    }
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;

        ListNode head = null;
        if (l1.val <= l2.val){
            head = l1;
            head.next = mergeTwoLists(l1.next, l2);
        } else {
            head = l2;
            head.next = mergeTwoLists(l1, l2.next);
        }
        return head;
    }
}

方法三:优先队列(堆)

/**
     * 优先级队列小顶堆
     * @param lists
     * @return
     */
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>(new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                return o1.val - o2.val;
            }
        });
        for(int i = 0; i < lists.length; i++){
            if(lists[i] != null){
                queue.offer(lists[i]);
            }
        }
        ListNode head = null;
        ListNode cur = null;
        while (!queue.isEmpty()){
            ListNode node = queue.poll();
            if(head == null){
                head = node;
                cur = head;
            }else {
                cur.next = node;
                cur = cur.next;
            }
            if(node.next != null){
                queue.offer(node.next);
            }
        }
        return head;
    }

    /**
     * 自己写堆 效率高点
     * @param lists
     * @return
     */
    public ListNode mergeKLists2(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }

        MinHeap minHeap = new MinHeap(lists.length);
        for(int i = 0; i < lists.length; i++){
            if(lists[i] != null){
                minHeap.insert(lists[i]);
            }
        }
        ListNode head = null;
        ListNode cur = null;
        while (!minHeap.isEmpty()){
            ListNode node = minHeap.remove();
            if(head == null){
                head = node;
                cur = head;
            }else {
                cur.next = node;
                cur = cur.next;
            }
            if(node.next != null){
                minHeap.insert(node.next);
            }
        }
        return head;
    }

    /**
     * 实现一个简易的堆看看效果
     */
    public class MinHeap{
        private ListNode[] lists;
        private int index = 1;      //索引开始为1 根据子节点查找父节点只需要除二 不用判断奇偶

        public MinHeap(int len){
            lists = new ListNode[len + 1];
        }

        public ListNode insert(ListNode node){
            if(index == lists.length){
                return lists[1];
            }
            int pos = index;
            lists[index++] = node;
            //堆化
            while (pos > 1){
                int midPos = pos >> 1;
                if(lists[pos].val < lists[midPos].val){
                    ListNode tmp = lists[midPos];
                    lists[midPos] = lists[pos];
                    lists[pos] = tmp;
                    pos = midPos;
                }else {
                    break;
                }
            }
            return lists[1];
        }

        public ListNode remove(){
            ListNode result = lists[1];
            lists[1] = lists[index - 1];
            lists[index - 1] = null;
            index--;
            int pos = 1;
            while (pos <= (index - 1)/2){
                int minPos = pos;
                int minValue = lists[pos].val;
                if(lists[pos].val > lists[pos * 2].val){
                    minPos = pos * 2;
                    minValue = lists[pos * 2].val;
                }
                if(index - 1 >= 2 * pos + 1){
                    //右节点存在
                    if(minValue > lists[2 * pos + 1].val){
                        minPos = 2 * pos + 1;
                        minValue = lists[2 * pos + 1].val;
                    }
                }
                //和minPos互换
                if(pos != minPos){
                    ListNode tmp = lists[pos];
                    lists[pos] = lists[minPos];
                    lists[minPos] = tmp;
                    pos = minPos;
                }else {
                    break;
                }
            }
            return result;
        }

        public boolean isEmpty(){
            return index <= 1;
        }
    }


215.Kth Largest Element in an Array(数组中的第k个最大元素)

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4

public class Solution215 {
	public int findKthLargest(int[] nums, int k) {
		PriorityQueue<Integer> queue=new PriorityQueue<Integer>(
				new Comparator<Integer>() {
					@Override
					public int compare(Integer o1, Integer o2) {
						// TODO Auto-generated method stub
						return o2-o1;
					}
				}
		) ;
		int len=nums.length;
		for(int i=0;i<len;i++) {
			queue.offer(nums[i]);
		}
		int num=0;
		for(int i=0;i<k;i++) {
			num=queue.poll();
		}
        return num;
    }

}

  1. The Skyline Problem(天际线的问题)

A city’s skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).

The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.

For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] .

The output is a list of “key points” (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], … ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.

For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ].

分析:(下面的小方框就是堆)
在这里插入图片描述

public List<List<Integer>> getSkyline(int[][] buildings) {
        
        int[][] arrange=new int[2*buildings.length][2];
        List<List<Integer>>ans = new ArrayList<>();
        if(buildings.length<=0){
            return ans;
        }
        for(int i=0;i<buildings.length;i++){
            //起点高度记为负数、终点高度记为正数。
            arrange[2*i][0]=buildings[i][0];
            arrange[2*i][1]=-buildings[i][2];
            arrange[2*i+1][0]=buildings[i][1];
            arrange[2*i+1][1]=buildings[i][2];
            
        }
        //sort  先按照横坐标进从小到大排序,如果横坐标相对,则按照纵坐标(高度)进行从小到大排序
        Arrays.sort(arrange,new Comparator<int[]>(){
            public int compare(int[] o1,int[] o2){
                if(o1[0]!=o2[0]){
                    return o1[0]-o2[0];
                }else{
                    return o1[1]-o2[1];//这里区间可以拼接,所以start在前 end 在后
                }
            }
        });
        // for height calculation
        //使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序来排序其元素(使用 Comparable)。 PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
        //默认容量是11
        PriorityQueue<Integer> que = new PriorityQueue(11,new Comparator<Integer>(){
            public int compare(Integer o1,Integer o2){
                return o2-o1;
            }
        });
        
        int pre=0;
        int cp=0;
        //sweep
        for(int i=0;i<arrange.length;i++){
            
            if(arrange[i][1]<0){
                //start
                que.offer(-arrange[i][1]);//起点高度入队
                
             }
            else {
            	 que.remove(arrange[i][1]);//终点  从队列删除相同高度的一个元素
            	 
            }//end  remove(Object o)方法用于删除队列中跟o相等的某一个元素(如果有多个相等,只删除一个)
            
            int now=0;//初始化高度为为0
            //now height
            if(que.size()>0){
                now=que.peek();//取堆顶元素(高度)。
            }
            // they are different store change point
            if(now!=pre){
                List<Integer> subans=new ArrayList<>();
                cp=arrange[i][0];
                pre=now;
                subans.add(cp);
                subans.add(pre);
                ans.add(subans);
            }     
        }
        return ans;
    }
   
发布了34 篇原创文章 · 获赞 4 · 访问量 1337

猜你喜欢

转载自blog.csdn.net/zj20165149/article/details/103944169