Leetcode - 周赛426

发布于:2024-12-06 ⋅ 阅读:(105) ⋅ 点赞:(0)

目录

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

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

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

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


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

两种做法:

  1. 暴力枚举长度为 1,2,3..... 的二进制全为 1 的值,直到它大于等于 n 
  2. 直接返回长度为 m  (m = n 的二进制长度) 的二进制全为 1 的值

代码如下:

//暴力枚举 O(logn)
class Solution {
    public int smallestNumber(int n) {
        int ans = 0, i = 0;
        while(ans < n){
            ans = (1 << i) - 1;
            i++;
        }
        return ans;
    }
}

//O(1)
class Solution {
    public int smallestNumber(int n) {
        int len = 32 - Integer.numberOfLeadingZeros(n);
        return (1 << len) - 1;
    }
}

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

本题其实是一道数学问题,设特殊数字的和为 x,异常值为 y,由题意得,2*x + y = sum(nums),这时可以看出,它实际上就是 leetcode 第一题两数之和,可以枚举 x,通过上述公式得到 y,判断其是否在 nums 数组中,如果在,求出其中的最大值。

代码如下:

class Solution {
    public int getLargestOutlier(int[] nums) {
        int n = nums.length, s = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for(int x : nums){
            map.merge(x, 1, Integer::sum);
            s += x;
        }
        int ans = -1001;
        for(int y : nums){
            int t = s - y;
            //需要特判 x == y 的情况,这时 map.get(t / 2) > 1
            if(t%2==0 && map.containsKey(t/2) && (t/2 != y || map.get(t/2) > 1))
                ans = Math.max(ans, y);
        }
        return ans;
    }
}

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

对于第一棵树中的第 i 个节点来说,新添加的边其中的一个节点必定是节点 i,因为如果不是 i,第二棵树中的每个节点与 i 节点的距离只会更大。

得出上述结论后,我们可以发现其实第二棵树中满足条件的节点个数是固定的,直接暴力枚举每一个与 i 相连的节点,求出与 i 节点距离小于等于 k - 1 (i 与 枚举的节点之间还有一条边)的最多节点数 mx。

这时,只需要求出第一棵树中第 i 节点满足条件的目标节点个数 + mx,就得到了 ans[i].

代码如下:

class Solution {
    public int[] maxTargetNodes(int[][] edges1, int[][] edges2, int k) {
        List<Integer>[] g1 = createTree(edges1);
        List<Integer>[] g2 = createTree(edges2);
        int n = edges1.length + 1;
        int m = edges2.length + 1;
        int mx = 0;
        for(int i=0; i<m; i++){
            mx = Math.max(mx, dfs(i, -1, k-1, g2) + (k==0?0:1));
        }
        int[] ans = new int[n];
        for(int i=0; i<n; i++){
            //与i距离<=k的节点数 + 本身 + 第二棵树中的节点个数
            ans[i] = dfs(i, -1, k, g1) + 1 + mx;
        }
        return ans;
    }
    int dfs(int x, int fa, int k, List<Integer>[] g){
        if(k <= 0) return 0;
        int res = 0;
        for(int y : g[x]){
            if(y != fa){
                res += dfs(y, x, k-1, g) + 1;
            }
        }
        return res;
    }
    List<Integer>[] createTree(int[][] edge){
        int n = edge.length + 1;
        List<Integer>[] g = new ArrayList[n];
        Arrays.setAll(g, e -> new ArrayList<>());
        for(int[] e : edge){
            int x = e[0], y = e[1];
            g[x].add(y);
            g[y].add(x);
        }
        return g;
    }
}

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

对于每棵树来说,假定一个根节点 root,分别计算出与 root 之间路径为奇,偶的节点数量 x, y(x + y = n),如果把 root 节点相邻的节点 reroot 当成根节点,可以发现所有与节点 root  路径为奇的节点现在都变成了与节点 reroot 路径为偶的节点,而所有与节点 root  路径为偶的节点现在都变成了与节点 reroot 路径为奇的节点,依次类推,得出结论:对于单独的一个树来说,目标节点的个数是max(x,y)

代码如下:

class Solution {
    public int[] maxTargetNodes(int[][] edges1, int[][] edges2) {
        List<Integer>[] g1 = createTree(edges1);
        List<Integer>[] g2 = createTree(edges2);
        int n = edges1.length + 1;
        int m = edges2.length + 1;
        mx = dfs(0, -1, 0, g2) + 1;
        mx = Math.max(mx, m - mx);
        int[] ans = new int[n];
        ans[0] = dfs(0, -1, 0, g1) + 1 + mx;
        dfs1(0, -1, ans, g1);
        return ans;
    }
    int mx;
    void dfs1(int x, int fa, int[] ans, List<Integer>[] g){
        int n = g.length;
        for(int y : g[x]){
            if(y != fa){
                ans[y] = n - ans[x] + 2*mx;
                dfs1(y, x, ans, g);
            }
        }
    }
    int dfs(int x, int fa, int k, List<Integer>[] g){
        int res = 0;
        for(int y : g[x]){
            if(y != fa){
                res += dfs(y, x, k+1, g) + k%2;
            }
        }
        return res;
    }
    List<Integer>[] createTree(int[][] edge){
        int n = edge.length + 1;
        List<Integer>[] g = new ArrayList[n];
        Arrays.setAll(g, e -> new ArrayList<>());
        for(int[] e : edge){
            int x = e[0], y = e[1];
            g[x].add(y);
            g[y].add(x);
        }
        return g;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到