[Leetcode Weekly Contest]312

链接:LeetCode

[Leetcode]2418. 按身高排序

给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。
对于每个下标 i,names[i] 和 heights[i] 表示第 i 个人的名字和身高。
请按身高 降序 顺序返回对应的名字数组 names 。

由于height各不相同,通过哈希存储即可。

class Solution {
    public String[] sortPeople(String[] names, int[] heights) {
        HashMap<Integer, String> height2Name = new HashMap<>();
        int n = names.length;
        for(int i=0;i<n;++i) {
            height2Name.put(heights[i], names[i]);
        }
        Arrays.sort(heights);
        var res = new String[n];
        for(int i=n-1;i>=0;--i) {
            res[n-1-i] = height2Name.get(heights[i]);
        }
        return res;
    }
}

[Leetcode]2419. 按位与最大的最长子数组

给你一个长度为 n 的整数数组 nums 。
考虑 nums 中进行 按位与(bitwise AND)运算得到的值 最大 的 非空 子数组。

  • 换句话说,令 k 是 nums 任意 子数组执行按位与运算所能得到的最大值。那么,只需要考虑那些执行一次按位与运算后等于 k 的子数组。
    返回满足要求的 最长 子数组的长度。

数组的按位与就是对数组中的所有数字进行按位与运算。
子数组 是数组中的一个连续元素序列。

由于 AND 不会让数字变大,那么最大值就是数组的最大值。因此题目实际上求的是数组中的最大值最多连续出现了几次。复杂度\(\mathcal{O}(n)\)

class Solution {
    public int longestSubarray(int[] nums) {
        int cur = 0, res = 0;
        int mx = Arrays.stream(nums).max().getAsInt();
        for(var num:nums) {
            if(num == mx) {
                cur ++;
                res = Math.max(res, cur);
            }
            else {
                cur = 0;
            }
        }
        return res;
    }
}

[Leetcode]2420. 找到所有好下标

给你一个大小为 n 下标从 0 开始的整数数组 nums 和一个正整数 k 。
对于 k <= i < n - k 之间的一个下标 i ,如果它满足以下条件,我们就称它为一个 好 下标:

  • 下标 i 之前 的 k 个元素是 非递增的 。
  • 下标 i 之后 的 k 个元素是 非递减的 。

按 升序 返回所有好下标。

先倒着遍历,得到从每个位置向后的最长连续非降序列的长度,然后正着遍历,得到每个位置向前的最长连续非增序列的长度,同时统计答案。

class Solution:
    def goodIndices(self, nums: List[int], k: int) -> List[int]:
        n = len(nums)
        ans = []
        dec = [1] * n
        for i in range(n - 2, k, -1):
            if nums[i] <= nums[i + 1]:
                dec[i] = dec[i + 1] + 1  # 递推
        inc = 1
        for i in range(1, n - k):
            if inc >= k and dec[i + 1] >= k:
                ans.append(i)
            if nums[i - 1] >= nums[i]:
                inc += 1  # 递推
            else:
                inc = 1
        return ans

[Leetcode] 2421. 好路径的数目

给你一棵 n 个节点的树(连通无向无环的图),节点编号从 0 到 n - 1 且恰好有 n - 1 条边。
给你一个长度为 n 下标从 0 开始的整数数组 vals ,分别表示每个节点的值。同时给你一个二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 和 bi 之间有一条 无向 边。
一条 好路径 需要满足以下条件:

  • 开始节点和结束节点的值 相同 。
  • 开始节点和结束节点中间的所有节点值都 小于等于 开始节点的值(也就是说开始节点的值应该是路径上所有节点的最大值)。

请你返回不同好路径的数目。
注意,一条路径和它反向的路径算作 同一 路径。比方说, 0 -> 1 与 1 -> 0 视为同一条路径。单个节点也视为一条合法路径。

并查集。按节点值从小到大考虑,同时用并查集合并时,总是从节点值小的点往节点值大的点合并,这样可以保证连通块的代表元的节点值是最大的。
对于节点 x 及其邻居 y,如果 y 所处的连通分量的最大节点值不超过 \(\textit{vals}[x]\),那么可以把 y 所处的连通块合并到 x 所处的连通块中。
如果此时这两个连通块的最大节点值相同,那么可以根据乘法原理,把这两个连通块内的等于最大节点值的节点个数相乘,加到答案中。

class Solution {
    int[] fa;

    public int numberOfGoodPaths(int[] vals, int[][] edges) {
        var n = vals.length;
        List<Integer>[] g = new ArrayList[n];
        Arrays.setAll(g, e -> new ArrayList<>());
        for (var e : edges) {
            int x = e[0], y = e[1];
            g[x].add(y);
            g[y].add(x); // 建图
        }

        fa = new int[n];
        for (var i = 0; i < n; i++) fa[i] = i;
        // size[x] 表示节点值等于 vals[x] 的节点个数,如果按照节点值从小到大合并,size[x] 也是连通块内的等于最大节点值的节点个数
        var size = new int[n];
        Arrays.fill(size, 1);
        var id = IntStream.range(0, n).boxed().toArray(Integer[]::new);
        Arrays.sort(id, (i, j) -> vals[i] - vals[j]);

        var ans = n;
        for (var x : id) {
            int vx = vals[x], fx = find(x);
            for (var y : g[x]) {
                y = find(y);
                if (y == fx || vals[y] > vx) continue; // 只考虑最大节点值比 vx 小的连通块
                if (vals[y] == vx) { // 可以构成好路径
                    ans += size[fx] * size[y]; // 乘法原理
                    size[fx] += size[y]; // 统计连通块内节点值等于 vx 的节点个数
                }
                fa[y] = fx; // 把小的节点值合并到大的节点值上
            }
        }
        return ans;
    }

    int find(int x) {
        if (fa[x] != x) fa[x] = find(fa[x]);
        return fa[x];
    }
}

参考:
LeetCode

posted @ 2022-09-26 20:15  Jamest  阅读(28)  评论(0编辑  收藏  举报