Skip to content

Latest commit

 

History

History
123 lines (117 loc) · 4.49 KB

File metadata and controls

123 lines (117 loc) · 4.49 KB

450 / 3803

第一题前缀和就放上来了。

题目: LeetCode 5437. 不同整数的最少数目. 给你一个整数数组 arr 和一个整数 k 。现需要从数组中恰好移除 k 个元素,请找出移除后数组中不同整数的最少数目。

//排序可以不需要用pair,因为只关心剩余的数字的个数,可以只用数字作为排序。
class Solution {
public:
    int findLeastNumOfUniqueInts(vector<int>& arr, int k) {
        unordered_map<int,int> m;
        for(int a: arr){
            m[a]++;
        }
        vector<pair<int,int>> count;
        for(auto it = m.begin(); it != m.end(); it++){
            count.push_back(*it);
        }
        sort(count.begin(),count.end(),[&](pair<int,int> p1,pair<int,int>p2){
            return p1.second < p2.second; 
        });
        int index = 0;
        for(auto p : count){
            if(p.second <= k){
                k -= p.second;
                index++;
            }else{
                break;
            }
        }
        return count.size()-index;
    }
};

题目: LeetCode 5438. 给你一个整数数组 bloomDay,以及两个整数 m 和 k 。现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好可以用于一束 花中。请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。

//二分法,在解空间里查找,给定天数判断是否满足条件,如果满足则往查找更小的值,如果不满足就找更大的天数。
class Solution {
public:
    //改成动态规划
    bool satisfy(vector<int>& bloomDay,int m, int k, int day){
        int count = 0;
        for(int i = 0; i < bloomDay.size(); ){
            int j ;
            for(j = 0; j < k ; j++){  
                if(i+j >= bloomDay.size() || bloomDay[i+j] > day){  
                    break;
                }    
            }
            if(j == k){
                count++;
            }
            i = i + (j>1?j:1);
            if(count >= m) return true;
        }
        return count >= m ;
    }
    int minDays(vector<int>& bloomDay, int m, int k) {
        if(m*k > bloomDay.size()) return -1;
        int left = INT_MAX;
        int right = 0;
        for(int day:bloomDay){
            if(day>right){
                right = day;
            }
            if(day<left){
                left = day;
            }
        }
        while(left<right){
            int mid = left + (right-left)/2;
            if(satisfy(bloomDay,m,k,mid)){  //如果满足条件,肯定在更小的区间里找
                right = mid;
            }else{  //不满足,则找更大的
                left = mid+1;
            }
        }
        return left;
        if(satisfy(bloomDay,m,k,left)) return left;
        return -1;
    }
};

题目: LeetCode 5188. 给你一棵树,树上有 n 个节点,按从 0 到 n-1 编号。树以父节点数组的形式给出,其中 parent[i] 是节点 i 的父节点。树的根节点是编号为 0 的节点。请你设计并实现 getKthAncestor(int node, int k) 函数,函数返回节点 node 的第 k 个祖先节点。如果不存在这样的祖先节点,返回 -1 。树节点的第 k 个祖先节点是从该节点到根节点路径上的第 k 个节点。

//因为可能树变成线性的表,因此需要用额外的空间记录更多的信息。
//dp[i][j] 代表第i个节点的2^j个父亲节点。
// 如果 a->b->c->d->e
// dp[a][0] = b ;
// dp[a][1] = dp[ dp[a][0] ] [0] = c
// dp[a][2] = dp[ dp[a][1] ] [1] = e  四个父亲节点
class TreeAncestor {
    vector<vector<int>> p;
public:
    TreeAncestor(int n, vector<int>& parent) {
        p = vector<vector<int>>(n, vector<int>(18, -1));
        for (int i = 0; i < n; ++i)
            p[i][0] = parent[i];
        // 18 代表正数最多18位,不会再比这个多了
        for (int k = 1; k < 18; ++k)
            for (int i = 0; i < n; ++i) {
                if (p[i][k - 1] == -1)
                    continue;
                //如果到-1了直接退出循环
                p[i][k] = p[p[i][k - 1]][k - 1];
            }
    }
    int getKthAncestor(int node, int k) {

        //这里把k看作二进制,当那一位为1时,才进行查找
        for (int i = 17; i >= 0; --i)
            if (k & (1 << i)) {
                node = p[node][i];
                if (node == -1)
                    break;
            }
        return node;
    }
};