1. 程式人生 > 其它 >Leetcode刷題 2021.02.09

Leetcode刷題 2021.02.09

技術標籤:刷題

Leetcode刷題 2021.02.09

Leetcode992 K 個不同整數的子陣列

給定一個正整數陣列 A,如果 A 的某個子陣列中不同整數的個數恰好為 K,則稱 A 的這個連續、不一定不同的子陣列為好子陣列。

(例如,[1,2,3,1,2] 中有 3 個不同的整數:1,2,以及 3。)

返回 A 中好子陣列的數目。

明天要回家過年了,不知道有沒有時間更新部落格了,還是希望部落格連續更新不斷吧。
今天的每日一題,困難題考查的的技巧方面就比較多了,如果沒有一定的演算法訓練的話還真的是做不出。其實就是把中等題改了一下,但是怎麼想得到的話就是另一回事了。

class Solution {
    public int subarraysWithKDistinct(int[] A, int K) {
        //恰好k個等於最多k個減去最多k - 1個。
        return helper(A, K) - helper(A, K - 1);
    }

    //至多包含k個不同整數的子陣列
    private int helper(int[] A, int K){
        int n = A.length;
        int[] map = new int[n + 1];
        int i = 0, j =
0, count = 0, res = 0; while (j < n){ //增大右視窗,維護一個數組,記錄不同整數的個數 if (map[A[j]] == 0) count++; map[A[j]]++; //如果不滿足條件了,就縮小左視窗 while (count > K){ map[A[i]]--; if (map[A[i]] == 0) count--; i++; }
//比如[1,2,1,2],i = 0, j = 3時,有4個滿足條件,即[2], [1,2], [2,1,2], [1,2,1,2]。就是以2為末尾的四個子陣列 res += j - i + 1; j++; } return res; } }

Leetcode475 供暖器

冬季已經來臨。 你的任務是設計一個有固定加熱半徑的供暖器向所有房屋供暖。

在加熱器的加熱半徑範圍內的每個房屋都可以獲得供暖。

現在,給出位於一條水平線上的房屋 houses 和供暖器 heaters 的位置,請你找出並返回可以覆蓋所有房屋的最小加熱半徑。

說明:所有供暖器都遵循你的半徑標準,加熱的半徑也一樣。

求一個最小值,二分查詢的老套路了,不斷嘗試並且收縮區間,直到某一個最小值符合條件就行了。

class Solution {
    public int findRadius(int[] houses, int[] heaters) {
        int i = 0, j = 1_000_000_000;
        //二分查詢模板,陣列沒說是有序的,先排序一下
        Arrays.sort(houses);
        Arrays.sort(heaters);
        while (i < j){
            int mid = i + (j - i) / 2;
            if (helper(houses, heaters, mid)){
                j = mid;
            }else{
                i = mid + 1;
            }
        }
        return i;
    }

    private boolean helper(int[] houses, int[] heaters, int mid){
        int index = 0, n = houses.length;
        //看看每個供暖期是否都能覆蓋到所有的房屋
        for(int i = 0; i < heaters.length; i++){
            int left = heaters[i] - mid, right = heaters[i] + mid;
            //如果在半徑內,就說明可以覆蓋
            while (index < n && houses[index] >= left && houses[index] <= right){
                index++;
            }
            if (index >= n) break;
            //如果當前的房屋大於左邊的半徑,說明肯定不能覆蓋到了
            if (houses[index] < left) return false;
        }
        return index < n ? false : true;
    }
}

Leetcode1702 吃蘋果的最大數目

有一棵特殊的蘋果樹,一連 n 天,每天都可以長出若干個蘋果。在第 i 天,樹上會長出 apples[i] 個蘋果,這些蘋果將會在 days[i] 天后(也就是說,第 i + days[i] 天時)腐爛,變得無法食用。也可能有那麼幾天,樹上不會長出新的蘋果,此時用 apples[i] == 0 且 days[i] == 0 表示。

你打算每天 最多 吃一個蘋果來保證營養均衡。注意,你可以在這 n 天之後繼續吃蘋果。

給你兩個長度為 n 的整數陣列 days 和 apples ,返回你可以吃掉的蘋果的最大數目。

貪心的思想,就好比平時吃東西,肯定是先把離保質期最近的吃到。可以用優先佇列進行模擬,按過期時間從小到達排列,遍歷的時候如果吃光了或者過了保質期了就出隊。

class Solution {
    public int eatenApples(int[] apples, int[] days) {
        PriorityQueue<Node> queue = new PriorityQueue<>((x, y) -> (x.expire - y.expire));
        int res = 0;
        for(int i = 0; i < apples.length || !queue.isEmpty(); i++){
        //如果有蘋果就加到佇列裡
            if (i < apples.length && apples[i] != 0){
                queue.offer(new Node(apples[i], i + days[i]));
            }
            //吃光了或者過了保質期了就出隊
            while(!queue.isEmpty() && (queue.peek().expire<= i || queue.peek().num == 0)){
                queue.poll();
            }
            //吃到離保質期最近的一個蘋果,同時吃掉的總數加1
            if (!queue.isEmpty()){
                queue.peek().num--;
                res++;
            }
        }
        return res;

    }
	//新建一個類,包含蘋果的數目和過期時間
    class Node{
        int num;
        int expire;

        public Node(int num, int expire){
            this.num = num;
            this.expire = expire;
        }
    }
}