【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;
    }
   
發佈了57 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章