1. 程式人生 > 其它 >[Leetcode Weekly Contest]269

[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