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];
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值