2020-12-29 1046, 面試題 17.14

SuperFeHanHan發表於2020-12-31

1046 最後一塊石頭的重量

有一堆石頭,每塊石頭的重量都是正整數。

每一回合,從中選出兩塊 最重的 石頭,然後將它們一起粉碎。假設石頭的重量分別為 x 和 y,且 x <= y。那麼粉碎的可能結果如下:
如果 x == y,那麼兩塊石頭都會被完全粉碎;
如果 x != y,那麼重量為 x 的石頭將會完全粉碎,而重量為 y 的石頭新重量為 y-x。
最後,最多隻會剩下一塊石頭。返回此石頭的重量。如果沒有石頭剩下,就返回 0。

示例:
輸入:[2,7,4,1,8,1]
輸出:1
解釋:
先選出 7 和 8,得到 1,所以陣列轉換為 [2,4,1,1,1],
再選出 2 和 4,得到 2,所以陣列轉換為 [2,1,1,1],
接著是 2 和 1,得到 1,所以陣列轉換為 [1,1,1],
最後選出 1 和 1,得到 0,最終陣列轉換為 [1],這就是最後剩下那塊石頭的重量。

解法1:

這裡嘗試採用Priority Queue的方式進行處理,每次最頂上的為2個最大的元素。

class Solution {

    // 自定義比較器,降序排列
	static Comparator<Integer> cmp = new Comparator<Integer>() {
		public int compare(Integer e1, Integer e2) {
			return e2 - e1;
		}
	};

    public int lastStoneWeight(int[] stones) {
        int l = stones.length;
        PriorityQueue<Integer> pq = new PriorityQueue<>(l, cmp);  //這裡我們每次用O(1)取出最大的兩個元素

        for(int i=0;i<l;i++)
            pq.add(stones[i]);
        
        while(pq.size()>1){
            int x = pq.poll();
            int y = pq.poll();
            if(x<y)
                pq.add(y-x);
            else if(y<x)
                pq.add(x-y);
        }
        // 出來size只可能為0或者1。
        if(pq.size()==1)
            return pq.poll();
        else
            return 0;
    }
}

面試題 17.14

設計一個演算法,找出陣列中最小的k個數。以任意順序返回這k個數均可。

示例:
輸入: arr = [1,3,5,7,2,4,6,8], k = 4
輸出: [1,2,3,4]

解法一:排序

public int[] smallestK(int[] arr, int k) {
        Arrays.sort(arr);
        int[] res = new int[k];
        for(int i=0;i<k;i++)
            res[i]=arr[i];
        return res;
    }

解法二: Priority Queue

public int[] smallestK(int[] arr, int k) {
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        for(int i=0;i<arr.length;i++)
            pq.add(arr[i]);
        
        int[] res = new int[k];
        for(int i=0;i<k;i++)
            res[i]=pq.poll();
        return res;
    }

解法三:Divide and Conquer

相關文章