[Leetcode Weekly Contest]269

链接:LeetCode

[Leetcode]2089. 找出数组排序后的目标下标

给你一个下标从 0 开始的整数数组 nums 以及一个目标元素 target 。

目标下标 是一个满足 nums[i] == target 的下标 i 。

将 nums 按 非递减 顺序排序后,返回由 nums 中目标下标组成的列表。如果不存在目标下标,返回一个 空 列表。返回的列表必须按 递增 顺序排列。

遍历即可。

class Solution {
    public List<Integer> targetIndices(int[] nums, int target) {
        List<Integer> res = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0; i<nums.length; ++i) {
            if(nums[i] == target) {
                res.add(i);
            }
        }
        return res;
    }
}

[Leetcode]2090. 半径为 k 的子数组平均值

给你一个下标从 0 开始的数组 nums ,数组中有 n 个整数,另给你一个整数 k 。
半径为 k 的子数组平均值 是指:nums 中一个以下标 i 为 中心 且 半径 为 k 的子数组中所有元素的平均值,即下标在 i - k 和 i + k 范围(含 i - k 和 i + k)内所有元素的平均值。如果在下标 i 前或后不足 k 个元素,那么 半径为 k 的子数组平均值 是 -1 。
构建并返回一个长度为 n 的数组 avgs ,其中 avgs[i] 是以下标 i 为中心的子数组的 半径为 k 的子数组平均值 。
x 个元素的 平均值 是 x 个元素相加之和除以 x ,此时使用截断式 整数除法 ,即需要去掉结果的小数部分。
例如,四个元素 2、3、1 和 5 的平均值是 (2 + 3 + 1 + 5) / 4 = 11 / 4 = 3.75,截断后得到 3 。

前缀和,注意分情况讨论

class Solution {
    public int[] getAverages(int[] nums, int k) {
        int n = nums.length;
        long subSum = 0;
        int[] res = new int[n];
        for(int i=0;(i < 2*k+1) && (i<n);++i) {
            subSum += nums[i];
        }
        for(int i=0; i<n; ++i) {
            if(i<k) res[i] = -1;
            else if(i>=n-k) res[i] = -1;
            else if(i==k) res[i] = (int)(subSum / (2*k+1));
            else {
                subSum += nums[i+k] - nums[i-k-1];
                res[i] = (int) (subSum / (2*k+1));
            }
        }
        return res;
    }
}

[Leetcode]2091. 从数组中移除最大值和最小值

给你一个下标从 0 开始的数组 nums ,数组由若干 互不相同 的整数组成。

nums 中有一个值最小的元素和一个值最大的元素。分别称为 最小值 和 最大值 。你的目标是从数组中移除这两个元素。

一次 删除 操作定义为从数组的 前面 移除一个元素或从数组的 后面 移除一个元素。

返回将数组中最小值和最大值 都 移除需要的最小删除次数。

根据题意,可以得到如下三种贪心策略:

  • 删除包含最小值和最大值的数组前缀;
  • 删除包含最小值和最大值的数组后缀;
  • 删除包含最小值的数组前缀(后缀),以及包含最大值的数组后缀(前缀)。

取三者最小值,即为答案。

class Solution {
    public int minimumDeletions(int[] nums) {
        int n = nums.length;
        int minInd=0, maxInd=0;
        int minVal=nums[0], maxVal=nums[0];
        for(int i=0;i<n;++i) {
            if(nums[i] < minVal) {
                minVal = nums[i];
                minInd = i;
            }
            else if (nums[i] > maxVal) {
                maxVal = nums[i];
                maxInd = i;
            }
        }
        int res = n;
        int leftInd=Math.min(minInd,maxInd), rightInd=Math.max(minInd,maxInd);
        res = Math.min(rightInd+1, n-leftInd);
        res = Math.min(res, leftInd+1+n-rightInd);
        return res;
    }
}

[Leetcode]2092. 找出知晓秘密的所有专家

给你一个整数 n ,表示有 n 个专家从 0 到 n - 1 编号。另外给你一个下标从 0 开始的二维整数数组 meetings ,其中 meetings[i] = [xi, yi, timei] 表示专家 xi 和专家 yi 在时间 timei 要开一场会。一个专家可以同时参加 多场会议 。最后,给你一个整数 firstPerson 。

专家 0 有一个 秘密 ,最初,他在时间 0 将这个秘密分享给了专家 firstPerson 。接着,这个秘密会在每次有知晓这个秘密的专家参加会议时进行传播。更正式的表达是,每次会议,如果专家 xi 在时间 timei 时知晓这个秘密,那么他将会与专家 yi 分享这个秘密,反之亦然。

秘密共享是 瞬时发生 的。也就是说,在同一时间,一个专家不光可以接收到秘密,还能在其他会议上与其他专家分享。

在所有会议都结束之后,返回所有知晓这个秘密的专家列表。你可以按 任何顺序 返回答案。

本质上是「静态连通性问题」,因此可以使用广度优先,深度优先搜索或者并查集解决。

class Solution {
        public List<Integer> findAllPeople(int n, int[][] meetings, int firstPerson) {
            int m = meetings.length;
            //1.按时间排序
            Arrays.sort(meetings, Comparator.comparingInt(x -> x[2]));

            //2.已知秘密的人设置为true
            boolean[] secret = new boolean[n];
            secret[0] = secret[firstPerson] = true;

            Map<Integer, List<Integer>> edges = new HashMap<>();//关联点

            for (int i = 0; i < m;) {
                // 找到这轮的范围
                int j = i;
                while (j + 1 < m && meetings[j + 1][2] == meetings[i][2]) {
                    ++j;
                }

                edges.clear();
                for (int k = i; k <= j; ++k) {
                    int x = meetings[k][0];
                    int y = meetings[k][1];
                    //加入关联点
                    List<Integer> l = edges.getOrDefault(x,new ArrayList<>());
                    l.add(y);
                    edges.put(x,l);
                    l = edges.getOrDefault(y,new ArrayList<>());
                    l.add(x);
                    edges.put(y,l);
                }

                //当前范围已知点
                Queue<Integer> queue = new LinkedList<>();
                for (int u: edges.keySet()) {
                    if (secret[u]) {
                        queue.offer(u);
                    }
                }

                //假设一个知道,则此轮关联点也必然知道
                while (!queue.isEmpty()) {
                    int u = queue.poll();
                    List<Integer> list = edges.getOrDefault(u,new ArrayList<>());
                    for (int v: list) {
                        if (!secret[v]) {
                            secret[v] = true;
                            queue.offer(v);
                        }
                    }
                }

                i = j + 1;
            }

            List<Integer> ans = new ArrayList<>();
            for (int i = 0; i < n; ++i) {
                if (secret[i]) {
                    ans.add(i);
                }
            }
            return ans;
        }
    }

Leetcode

原文地址:https://www.cnblogs.com/hellojamest/p/15626090.html