1. 程式人生 > 實用技巧 >[Leetcode Weekly Contest]202

[Leetcode Weekly Contest]202

連結:LeetCode

[Leetcode]5185. 存在連續三個奇數的陣列

給你一個整數陣列 arr,請你判斷陣列中是否存在連續三個元素都是奇數的情況:如果存在,請返回 true ;否則,返回 false 。

暴力即可。

class Solution {
public:
    bool threeConsecutiveOdds(vector<int>& arr) {
        int count=0;
        for(auto n:arr){
            if(n&1){
                count ++;
            }
            else{
                count = 0;
            }
            if(count==3){
                return true;
            }
        }
        return false;
    }
};

[Leetcode]5488. 使陣列中所有元素相等的最小運算元

存在一個長度為 n 的陣列 arr ,其中\(arr[i] = (2 * i) + 1 ( 0 <= i < n )\)
一次操作中,你可以選出兩個下標,記作 x 和 y ( 0 <= x, y < n )並使\(arr[x]\)減去 1 、\(arr[y]\)加上 1 (即\(arr[x] -=1\)\(arr[y] += 1\))。最終的目標是使陣列中的所有元素都 相等 。題目測試用例將會 保證 :在執行若干步操作後,陣列中的所有元素最終可以全部相等。
給你一個整數 n,即陣列的長度。請你返回使陣列 arr 中所有元素相等所需的 最小運算元 。

找規律。陣列 arr 滿足\(arr[i] = (2 * i) + 1 ( 0 <= i < n )\)。其所有元素的累加和為 (n + 2)*n。有累加和可知,操作完成後,每個元素均為 n+2。操作前,arr 中總共有 x 個元素小於 n+2,x = n/2-1。這 x 個元素的累加和為(n+3)(n-1)/4。操作後,前 x 個元素的累加和為 (n+2)(n-2)/2。因為每次操作,小於 n+2 的元素的累加和會增加一,所以兩和作差即為答案,(n^2)/4。(整數相除會向下取整哦)。

class Solution {
public:
    int minOperations(int n) {
        return n*n/4;
    }
};

[Leetcode]5489. 兩球之間的磁力

在代號為 C-137 的地球上,Rick 發現如果他將兩個球放在他新發明的籃子裡,它們之間會形成特殊形式的磁力。Rick 有 n 個空的籃子,第 i 個籃子的位置在\(position[i]\),Morty 想把 m 個球放到這些籃子裡,使得任意兩球間 最小磁力 最大。
已知兩個球如果分別位於 x 和 y ,那麼它們之間的磁力為\(|x - y|\)
給你一個整數陣列 position 和一個整數 m ,請你返回最大化的最小磁力。

二分查詢。題意求最大化最小,類似這樣的求最大化最小值、最小化最大值等都可以用二分搜尋解決。首先要找到二分搜尋的邊界,根據題意,要返回的是最小磁力,所以第一步要找到最小磁力的最小可能取值和最大可能取值。
對於最小可能取值,當然就是給定陣列中距離最近的兩個位置之間的磁力,所以對陣列進行排序,並遍歷陣列找到相鄰兩個位置的最小距離。對於最大可能取值,一共有m個球,所以有 m - 1 個間隔,最大的可能取值便是最平均的取值,所以根據給定陣列最大值與最小值之差與間隔數的比值計算出平均距離,就是給定的最大可能取值。
確定好了邊界後,每次二分搜尋時需要判斷當前計算值是否滿足條件,這裡我們引入 check 函式,對當前計算出的最小磁力進行驗證。驗證過程使用貪心演算法,遍歷陣列,若找到兩位置之間距離大於等於最小磁力,則計數值加1,最後只需要判斷總計數值是否大於等於給定間隔數 m - 1即可。
在判斷計算值滿足條件與否之後,我們要對二分搜尋邊界進行轉化,由於題目要求的是最大化的最小磁力,所以若當前計算出的最小磁力滿足條件,我們要將左邊界右移,去判斷稍大一點的數值是否滿足條件;若當前計算出的最小磁力不滿足條件,我們要將右邊界左移,判斷稍小的數值是否滿足條件。由於每次滿足條件後左邊界右移,所以左邊界的左邊一個數值是一定滿足條件的,所以最後返回值為 l - 1,具體返回值根據邊界移動的判定規則進行判斷。

class Solution {
public:
    bool check(vector<int>& position,int m,int minDiff) {
        int n=position.size(),count=1,target=position[0]+minDiff;
        for(auto n:position){
            if(n>=target) {
                target=n+minDiff;
                count ++;
            }
        }
        return count>=m;
    }

    int maxDistance(vector<int>& position, int m) {
        sort(position.begin(),position.end());
        int n=position.size();
        int diff  = position[n-1] - position[0];
        if(m==2){
            return diff;
        }
        int le=INT_MAX,hi=diff/(m-1);
        for(int i=1;i<n;++i){
            le=min(le,position[i]-position[i-1]);
        }
        while(le<=hi){
            int mid=le+((hi-le)>>1);
            if(check(position,m,mid)) le=mid+1;
            else hi=mid-1;
        }
        return le-1;
    }
};

[Leetcode]5490. 吃掉 N 個橘子的最少天數

廚房裡總共有 n 個橘子,你決定每一天選擇如下方式之一吃這些橘子:

  • 吃掉一個橘子。
  • 如果剩餘橘子數 n 能被 2 整除,那麼你可以吃掉 n/2 個橘子。
  • 如果剩餘橘子數 n 能被 3 整除,那麼你可以吃掉 2*(n/3) 個橘子。

每天你只能從以上 3 種方案中選擇一種方案。
請你返回吃掉所有 n 個橘子的最少天數。

動態規劃。實際上可以通過記憶化搜尋的方法解決。

class Solution {
public:
    unordered_map<int,int> um;

    int minDays(int n) {
        if(n==0) return 0;
        if(n==1) return 1;
        if(um.count(n)) return um[n];
        um[n] = min(minDays(n/2)+n%2,minDays(n/3)+n%3)+1;
        return um[n];
    }
};

參考:
Leetcode