leetcode 第193場周賽

一維數組的動態和 不同整數的最少數目 製作m束花所需的最少天數 樹節點的第K個祖先
3分 簡單 4分 中等 5分 中等 6分 困難

1480 一維數組的動態和

 

class Solution {
public:
    vector<int> runningSum(vector<int>& nums) {
        int sum=0;
        vector<int>ans;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
            ans.push_back(sum);
        }
        return ans;
    }
};

1481 不同整數的最少數目

對數組進行處理,用新的結構體node來存儲,val表示數的值,num表示數組裏這個數有幾個

那麼按個數從小到大排序,爲了移除k個元素後不同整數的數目最少,貪心的想,應該先移除個數少的的數

struct node{
    int val,num;
    bool operator<(const node &b)const{
        return num<b.num;
    }
}a[100050];
class Solution {
public:
    int findLeastNumOfUniqueInts(vector<int>& arr, int k) {
        int n=arr.size();
        sort(arr.begin(),arr.end());
        int val=arr[0],num=1,m=1;
        for(int i=1;i<n;i++){
            if(arr[i]!=arr[i-1]){
                a[m].val=val;
                a[m].num=num;
                m++;
                val=arr[i];
                num=1;
            }
            else num++;
        }
        a[m].val=val;
        a[m].num=num;
        sort(a+1,a+1+m);
        int ans=0;
        for(int i=1;i<=m;i++){
            if(a[i].num>=k){
                ans=m-i;
                if(a[i].num>k) ans++;
                break;
            }   
            k-=a[i].num; 
        }
        return ans;
    }
};

 


1482 製作m束花所需的最少天數

二分答案,即需要等待的最少的天數x,x的範圍爲(l,r),l爲1,r爲數組中bloomDay[i]的最大值

貪心的選取連續的k朵花,只要滿足了就取,這樣一定是最優的

pre記錄的是不滿足條件的最後一個位置,即pre+1到i這段區間都是符合條件,即小於等於x

若這段區間距離大於等於k,則滿足條件

class Solution {
public:
    bool check(vector<int>& bloomDay,int m,int k,int x){
        int n=bloomDay.size();
        int pre=-1;
        for(int i=0;i<n;i++){
            if(bloomDay[i]<=x){
                if(i-pre>=k){
                    m--;
                    if(m==0) return true;
                    pre=i;
                }
            }
            else pre=i;
        }
        return false;
    }
    int minDays(vector<int>& bloomDay, int m, int k) {
        int ans=-1,l=1,r=0;
        for(auto it:bloomDay) r=max(r,it);
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(bloomDay,m,k,mid)){
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        return ans;
    }
};

 


1483 樹節點的第K個祖先

倍增法求第K個祖先 複雜度是nlogn

爲了方便處理,先將序號轉化成從一開始的

ve[i]存的是i的兒子節點

f[u][0]//表示節點u的父親,即從該節點到根節點路徑上的第(1<<0)個節點
f[u][1]//表示節點u的父親的父親,即從該節點到根節點路徑上的第(1<<1)個節點
f[u][i]//表示從該節點到根節點路徑上的第(1<<i)個節點

先跑一邊dfs得到f數組

查詢某節點到根節點路徑上的第k個節點時,即k爲查詢節點向上走k部,從大到小枚舉f數組的第二個參數i,如果(1<<i)<=k,說明此時節點可以向上走(1<<i)步,k-=(1<<i) ,直到k爲0結束

            int ans=node;
            for(int i=20;i>=0;i--)
            {
                if((1<<i)<=k){
                    k-=(1<<i);
                    ans=f[ans][i];
                }
            }

 

const int maxn=100050;
class TreeAncestor {
public:
    void dfs(int u,int fa){
        dep[u]=dep[fa]+1;
        for(int i=1;(1<<i)<=dep[u];i++){
            f[u][i]=f[f[u][i-1]][i-1];
        }
        for(auto v:ve[u]){
            f[v][0]=u;
            dfs(v,u);
        }
    }
    TreeAncestor(int n, vector<int>& parent) {
        for(int i=0;i<n;i++){
            ve[parent[i]+1].push_back(i+1);
        }
        dfs(1,0);
    }
​
    int getKthAncestor(int node, int k) {
        node++;
        if(dep[node]>=k){
            int ans=node;
            for(int i=20;i>=0;i--)
            {
                if((1<<i)<=k){
                    k-=(1<<i);
                    ans=f[ans][i];
                }
            }
            return (ans-1);
        }
        else return -1;
    }
    int num,head[maxn],dep[maxn],f[maxn][23];
    vector<int>ve[maxn];
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章