1. 程式人生 > 實用技巧 >Leetcode 周賽#202 題解

Leetcode 周賽#202 題解

本週的周賽題目質量不是很高,因此只給出最後兩題題解()。

1552 兩球之間的磁力 #二分答案

題目連結

題意

n個空籃子,第i個籃子位置為position[i],現希望將m個球放到這些空籃子,使得任意兩球間最小磁力最大。(其中,磁力簡化為兩點位置之差)

分析

該題是二分答案的裸題,詳細見程式碼

class Solution {
public:
    bool Judge(vector<int>& a, int x, int m){
        int cnt = 1,lastpos = a[0];
        for (int i = 1; i < (int)a.size(); i++){
            if(a[i] - lastpos >= x){ //兩點間距是否大於答案x
                cnt++;
                lastpos = a[i];
            }
            if(cnt == m) return true;
        }
        return false;
    }
    int maxDistance(vector<int>& position, int m) { //該二分演算法,是考慮[1, n+1)
        sort(position.begin(), position.end()); //記得先排序!!!
        int lo = 0x3f3f3f3f;
        int hi = position[position.size() - 1] - position[0] + 1; //確定兩個籃子最大間距,為二分的上界,注意要+1!!!
        for (int i = 1; i < (int)position.size(); i++){
            int delt = position[i] - position[i - 1]; //確定兩個籃子的最小間距,為二分的下界
            lo = min(delt, lo);
        }
        while(lo < hi){
            int mid = (lo + hi) >> 1;
            if(Judge(position, mid, m)) //估計答案
                lo = mid + 1; //答案可以再高一些
            else
                hi = mid; //說明該答案下的間距無法將所有球放完
        }
        return lo-1;
    }
};

1553 吃掉N個橘子的最少天數 #記憶化搜尋

題目連結

題意

給定n(<= 2e9)個橘子,每一天你只能從以下三種方案中選擇一種:

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

現要求吃掉這n個橘子的最少天數。

分析

容易知道,當n>3時,吃掉n/2個橘子,剩餘橘子數即為n/2;吃掉2*(n/3)個橘子,剩餘橘子樹即為n/3

那我們先預處理,將n$\leq$3的情況記錄下來。接下來考慮轉移方程。

起初我考慮有三個轉移方向:n-1n/2n/3,並用陣列記憶化。在如此龐大的資料範圍,不但陣列無法承受,而且會分出更多的子問題。

為了應對空間問題,可以考慮用map來記憶化。

為了應對時間問題,我們分析到,對於當前剩餘橘子數n

  • 方案二分析:\(n\ Mod\ 3 = 0, 1, 2\),餘數為0,顯然吃掉n/3個橘子即可;餘數為1時,說明我們需要用n/3天的時間將3的倍數個橘子吃完,最後剩下一個橘子,需要1天;同理,餘數為2時,說明我們用n/3天將3的倍數個橘子吃完後,還需要用兩天時間(使用方案一)將剩下2個橘子吃完。
  • 方案三如方案二分析同理,我們要用n/2將2的倍數個橘子吃完後,還需要\(n\ Mod\ 2\)天(使用方案一,且已經預處理過)吃掉剩餘的橘子。

因此,我們只需要交給程式去考慮當前的n是選擇方案二更優還是方案三,自頂而下向下遞迴。無需再考慮n-1

的方向,同時無需考慮當前的n是否被3整除/被2整除。轉移方程見下方程式碼。

class Solution {
private:
    unordered_map<int, int> dp;
public:
    int minDays(int n) {
        if(n == 1)           return dp[1] = 1;
        else if(n == 2)      return dp[2] = 2;
        else if(n == 3)      return dp[3] = 2;
        else if(dp.count(n)) return dp[n];
        else return dp[n] = min(minDays(n / 3) + 1 + n % 3,
                                minDays(n / 2) + 1 + n % 2);
        
    }
};

在筆記本最後幾點電量寫完題解qaq