LeetCode---426周赛

题目列表

3370. 仅含置位位的最小整数

3371. 识别数组中的最大异常值

3372. 连接两棵树后最大目标节点数目 I

3373. 连接两棵树后最大目标节点数目 II

一、仅含置位位的最小整数

题目要求我们返回二进制数位全为1,且大于 n 的最小的整数,我们可以直接从小到大枚举答案,也可以直接计算出答案,比如 5 的二进制为 101,返回 111,即7,8的二进制为1000,返回1111,即15,也就是说我们返回的值的二级制位数等于 n 的二进制位数,即返回值为 (1<<bit_length)-1,其中 bit_length 为 n 的二进制位数,代码如下

cpp 复制代码
// 1、模拟
class Solution {
public:
    int smallestNumber(int n) {
        int ans = 0;
        for(int i = 0; i < 32; i++){
            if(ans >= n) return ans;
            ans |= 1 << i;
        }
        return -1;
    }
};

// 2、直接按公式计算
class Solution {
public:
    int smallestNumber(int n) {
        // __builtin_clz 用来计算 n 的二进制前导零的个数
        return (1 << (32 - __builtin_clz(n))) - 1;
    }
};

二、识别数组中的最大异常值

首先,我们要先清楚数组中元素的关系,设异常值为 x,特殊值为 y,则 x + 2y = sum,sum为数组和,根据等式的关系,我们可以枚举异常值 x,然后看是否存在一个元素 y = (sum - x)/2 (可以用哈希表记录每个元素的出现次数) 如果存在,则 y 可以为异常值,取 max 即可,代码如下

cpp 复制代码
class Solution {
public:
    int getLargestOutlier(vector<int>& nums) {
        int n = nums.size(), sum = 0, ans = INT_MIN;
        unordered_map<int,int>mp;
        for(auto x:nums) mp[x]++, sum += x;
        for(auto x:nums){
            if((sum - x) % 2 == 0){ // 必须是偶数
                int y = (sum - x) / 2;
                if(mp.count(y) && (x != y || mp[x] > 1)){ // 可能会出现 x = y 的情况,此时 mp[x] > 1
                    ans = max(ans, x);
                }
            }
        }
        return ans;
    }
};

三、连接两棵树后最大目标结点个数 I

首先,我们来思考一棵树中每个结点的最大目标结点个数如何计算?由于数据范围比较小,我们可以给每一个结点都用 dfs 计算一次目标节点个数。

那么如果两个树要连接在一起呢?我们需要考虑枚举哪两个结点连接的问题吗?不需要

1、对于Tree1,根据题目中目标节点的定义,我们肯定是将需要计算的结点当作连接的结点,这样才能让该结点到Tree2的结点的边数尽可能少,从而让目标节点的个数尽可能的多

2、对Tree2,根据(1),其实问题就变成了Tree2中哪个结点的目标结点的个数最多,只不过距离变为 k - 1,可以用相同的方法计算出每个结点的目标节点的个数,然后取max即可

代码如下

cpp 复制代码
class Solution {
    vector<int> getTargetNodes(vector<vector<int>>& edges, int k){
        int n = edges.size();
        vector<vector<int>> g(n + 1);
        for(auto e : edges){
            g[e[0]].push_back(e[1]);
            g[e[1]].push_back(e[0]);
        }
        int i;
        vector<int> ret(n + 1);
        function<void(int,int,int)> dfs = [&](int x, int fa, int d){
            if(d <= k) {
                ret[i]++;
                for(int y : g[x]){
                    if(y != fa){
                        dfs(y, x, d + 1);
                    }
                }
            }
        };
        for(i = 0; i < n + 1; i++)
            dfs(i, -1, 0);
        return ret;
    }
public:
    vector<int> maxTargetNodes(vector<vector<int>>& edges1, vector<vector<int>>& edges2, int k) {
        int mx = ranges::max(getTargetNodes(edges2, k - 1)); // 由于Tree2需要和Tree1连接,会多出一条边,所以计算目标结点时的 k 需要减一
        auto ans = getTargetNodes(edges1, k);
        for(auto & x : ans) x += mx;
        return ans;
    }
};

四、连接两棵树后最大目标结点个数 II

注意:这题的题目和第三题并不一样,一定要仔细读题,但是思路大题相同。

题目说结点之间的距离为偶数时,互为目标节点,这里我们只用关心奇偶性即可,同时,如果我们手玩一下示例一,就会发现:

所以我们只要对一棵树进行一次 dfs 就能算出该树上所有结点的目标节点的个数,然后依旧是将两棵树分别进行计算即可,代码如下

cpp 复制代码
class Solution {
    vector<int> getCnt(vector<vector<int>>& g){
        int n = g.size();
        vector<int> cnt(2);
        // 距离 0 结点为 偶数 的数字互为目标结点
        // 距离 0 结点为 奇数 的数字互为目标节点
        auto dfs = [&](auto&& dfs, int x, int fa, int d)->void{
            cnt[d]++;
            for(int y: g[x]){
                if(y != fa){
                    dfs(dfs, y, x, d ^ 1);
                }
            }
        };
        dfs(dfs, 0, -1, 0);
        return cnt;
    }
public:
    vector<int> maxTargetNodes(vector<vector<int>>& edges1, vector<vector<int>>& edges2) {
        int n = edges1.size() + 1;
        int m = edges2.size() + 1;
        vector<vector<int>> g1(n), g2(m);
        for(auto e:edges1){
            g1[e[0]].push_back(e[1]);
            g1[e[1]].push_back(e[0]);
        }
        for(auto e:edges2){
            g2[e[0]].push_back(e[1]);
            g2[e[1]].push_back(e[0]);
        }
        vector<int> cnt = getCnt(g1);
        int mx = ranges::max(getCnt(g2));
        vector<int> ans(n, mx);
        auto dfs = [&](auto&& dfs, int x, int fa, int d)->void{
            ans[x] += cnt[d];
            for(int y:g1[x]){
                if(y != fa){
                    dfs(dfs, y, x, d ^ 1);
                }
            }
        };
        dfs(dfs, 0, -1, 0);
        return ans;
    }
};
相关推荐
油泼刀削面9 分钟前
[控制理论]—带死区的PID控制算法及仿真
算法
金创想35 分钟前
十大排序简介
算法·排序算法·十大排序
执着的小火车1 小时前
【2024华为OD-E卷-100分-boss的收入】(题目+思路+Java&C++&Python解析)
数据结构·算法·华为od·华为·排序算法
終不似少年遊*1 小时前
机器学习模型评估指标
人工智能·算法·机器学习·回归·模型评价
剁椒排骨1 小时前
冒泡排序(C语言)
c语言·算法·排序算法·算法与结构
code04号2 小时前
图论:三维搜索
算法·图论
code04号2 小时前
图论:Tarjan算法的使用,找连通分量、割点、桥
算法·图论
ExRoc2 小时前
蓝桥杯真题 - 魔法阵 - 题解
c++·算法·蓝桥杯
m0_749317523 小时前
蓝桥杯训练
java·学习·职场和发展·蓝桥杯
夜泉_ly3 小时前
算法 -归并排序
算法