• [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

  • 相关阅读:
    整数因子分解问题(递归分治法、动态规划)
    背包问题(动态规划 C/C++)
    划分问题(Java 动态规划)
    算法:Common Subsequence(动态规划 Java 最长子序列)
    算法:矩阵连乘(Java)动态规划
    Frogs‘ Neighborhood(POJ 1659 C/C++)
    算法:线性时间选择(C/C++)
    sort(hdu oj 1425)计数排序和快速排序
    快速排序(递归和分治)
    a^b(取模运算)
  • 原文地址:https://www.cnblogs.com/hellojamest/p/15626090.html
Copyright © 2020-2023  润新知