天天看點

LeetCode Weekly Contest 1805356. 矩陣中的幸運數5357. 設計一個支援增量操作的棧5179. 将二叉搜尋樹變平衡5359. 最大的團隊表現值

5356. 矩陣中的幸運數

給你一個 m * n 的矩陣,矩陣中的數字 各不相同 。請你按 任意 順序傳回矩陣中的所有幸運數。

幸運數是指矩陣中滿足同時下列兩個條件的元素:

在同一行的所有元素中最小

在同一列的所有元素中最大

示例 1:

輸入:matrix = [[3,7,8],[9,11,13],[15,16,17]]

輸出:[15]

解釋:15 是唯一的幸運數,因為它是其所在行中的最小值,也是所在列中的最大值。

示例 2:

輸入:matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]]

輸出:[12]

解釋:12 是唯一的幸運數,因為它是其所在行中的最小值,也是所在列中的最大值。

示例 3:

輸入:matrix = [[7,8],[1,2]]

輸出:[7]

提示:

m == mat.length

n == mat[i].length

1 <= n, m <= 50

1 <= matrix[i][j] <= 10^5

矩陣中的所有元素都是不同的

代碼

class Solution {
    public List<Integer> luckyNumbers (int[][] matrix) {
        int m = matrix.length, n = matrix[0].length, i = 0, j = 0, minIdx = -1, minVal = Integer.MAX_VALUE;
        boolean flag = false;
        ArrayList<Integer> ans = new ArrayList<>();
        for (i=0; i<m; ++i) {
            minIdx = -1;
            minVal = Integer.MAX_VALUE;
            flag = false;
            for (j=0; j<n; ++j) {
                if (matrix[i][j] < minVal) {
                    minVal = matrix[i][j];
                    minIdx = j;
                }
            }
            for (j=0; j<m; ++j) {
                if (matrix[j][minIdx] > minVal) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                ans.add(minVal);
            }
        }
        return ans;
    }
}
           

5357. 設計一個支援增量操作的棧

請你設計一個支援下述操作的棧。

實作自定義棧類 CustomStack :

CustomStack(int maxSize):用 maxSize 初始化對象,maxSize 是棧中最多能容納的元素數量,棧在增長到 maxSize 之後則不支援 push 操作。

void push(int x):如果棧還未增長到 maxSize ,就将 x 添加到棧頂。

int pop():傳回棧頂的值,或棧為空時傳回 -1 。

void inc(int k, int val):棧底的 k 個元素的值都增加 val 。如果棧中元素總數小于 k ,則棧中的所有元素都增加 val 。

示例:

輸入:

[“CustomStack”,“push”,“push”,“pop”,“push”,“push”,“push”,“increment”,“increment”,“pop”,“pop”,“pop”,“pop”]

[[3],[1],[2],[],[2],[3],[4],[5,100],[2,100],[],[],[],[]]

輸出:

[null,null,null,2,null,null,null,null,null,103,202,201,-1]

解釋:

CustomStack customStack = new CustomStack(3); // 棧是空的 []
customStack.push(1);                          // 棧變為 [1]
customStack.push(2);                          // 棧變為 [1, 2]
customStack.pop();                            // 傳回 2 --> 傳回棧頂值 2,棧變為 [1]
customStack.push(2);                          // 棧變為 [1, 2]
customStack.push(3);                          // 棧變為 [1, 2, 3]
customStack.push(4);                          // 棧仍然是 [1, 2, 3],不能添加其他元素使棧大小變為 4
customStack.increment(5, 100);                // 棧變為 [101, 102, 103]
customStack.increment(2, 100);                // 棧變為 [201, 202, 103]
customStack.pop();                            // 傳回 103 --> 傳回棧頂值 103,棧變為 [201, 202]
customStack.pop();                            // 傳回 202 --> 傳回棧頂值 202,棧變為 [201]
customStack.pop();                            // 傳回 201 --> 傳回棧頂值 201,棧變為 []
customStack.pop();                            // 傳回 -1 --> 棧為空,傳回 -1
           

提示:

1 <= maxSize <= 1000

1 <= x <= 1000

1 <= k <= 1000

0 <= val <= 100

每種方法 increment,push 以及 pop 分别最多調用 1000 次

代碼

class CustomStack {
    private int maxSize;
    private ArrayList<Integer> stack;

    public CustomStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new ArrayList<>();
    }
    
    public void push(int x) {
        if (stack.size() < maxSize) {
            stack.add(x);
        }
    }
    
    public int pop() {
        if (stack.isEmpty()) {
            return -1;
        } else {
            return stack.remove(stack.size() - 1);
        }
    }
    
    public void increment(int k, int val) {
        for (int i = 0, s = stack.size(); i < k; ++i) {
            if (i >= s) {
                break;
            }
            stack.set(i, stack.get(i) + val);
        }
    }
}

/**
 * Your CustomStack object will be instantiated and called as such:
 * CustomStack obj = new CustomStack(maxSize);
 * obj.push(x);
 * int param_2 = obj.pop();
 * obj.increment(k,val);
 */
           

5179. 将二叉搜尋樹變平衡

給你一棵二叉搜尋樹,請你傳回一棵 平衡後 的二叉搜尋樹,新生成的樹應該與原來的樹有着相同的節點值。

如果一棵二叉搜尋樹中,每個節點的兩棵子樹高度差不超過 1 ,我們就稱這棵二叉搜尋樹是 平衡的 。

如果有多種構造方法,請你傳回任意一種。

示例:

LeetCode Weekly Contest 1805356. 矩陣中的幸運數5357. 設計一個支援增量操作的棧5179. 将二叉搜尋樹變平衡5359. 最大的團隊表現值
LeetCode Weekly Contest 1805356. 矩陣中的幸運數5357. 設計一個支援增量操作的棧5179. 将二叉搜尋樹變平衡5359. 最大的團隊表現值

輸入:root = [1,null,2,null,3,null,4,null,null]

輸出:[2,1,3,null,null,null,4]

解釋:這不是唯一的正确答案,[3,1,4,null,2,null,null] 也是一個可行的構造方案。

提示:

樹節點的數目在 1 到 10^4 之間。

樹節點的值互不相同,且在 1 到 10^5 之間。

思路

  1. 将二叉搜尋樹變成數組
  2. 将數組變成平衡二叉搜尋樹

代碼

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private void treeToArray(TreeNode root, ArrayList<Integer> arr) {
        if (root == null) {
            return;
        }
        treeToArray(root.left, arr);
        arr.add(root.val);
        treeToArray(root.right, arr);
    }
    
    private TreeNode arrayToBST(ArrayList<Integer> arr, int left, int right) {
        if (right - left <= 0) {
            return null;
        }
        int mid = (left + right) / 2;
        TreeNode root = new TreeNode(arr.get(mid));
        root.left = arrayToBST(arr, left, mid);
        root.right = arrayToBST(arr, mid+1, right);
        return root;
    }
    
    public TreeNode balanceBST(TreeNode root) {
        ArrayList<Integer> sorted = new ArrayList<>();
        treeToArray(root, sorted);
        return arrayToBST(sorted, 0, sorted.size());
    }
}
           

5359. 最大的團隊表現值

公司有編号為 1 到 n 的 n 個工程師,給你兩個數組 speed 和 efficiency ,其中 speed[i] 和 efficiency[i] 分别代表第 i 位工程師的速度和效率。請你傳回由最多 k 個工程師組成的 ​​​​​​最大團隊表現值 ,由于答案可能很大,請你傳回結果對 10^9 + 7 取餘後的結果。

團隊表現值 的定義為:一個團隊中「所有工程師速度的和」乘以他們「效率值中的最小值」。

示例 1:

輸入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 2

輸出:60

解釋:

我們選擇工程師 2(speed=10 且 efficiency=4)和工程師 5(speed=5 且 efficiency=7)。他們的團隊表現值為 performance = (10 + 5) * min(4, 7) = 60 。

示例 2:

輸入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 3

輸出:68

解釋:

此示例與第一個示例相同,除了 k = 3 。我們可以選擇工程師 1 ,工程師 2 和工程師 5 得到最大的團隊表現值。表現值為 performance = (2 + 10 + 5) * min(5, 4, 7) = 68 。

示例 3:

輸入:n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4

輸出:72

提示:

1 <= n <= 10^5

speed.length == n

efficiency.length == n

1 <= speed[i] <= 10^5

1 <= efficiency[i] <= 10^8

1 <= k <= n

思路

貪心。首先将工程師數組按(效率,速度)雙鍵降序排序。維護一個大小為k的小頂堆,周遊排序過後的數組,更新小頂堆為目前數組中最大的k個工程師的speed(如果周遊過的數組長度不足k,則為所有周遊過的speed),小頂堆中的元素之和與最新放入小頂堆的工程師的efficiency相乘更新目前的最大值。

代碼

class Solution {
    private static final long mod = 1000000007;
    
    private class Engineer implements Comparable<Engineer> {
        public int s, e;
        
        public Engineer(int s, int e) {
            this.s = s;
            this.e = e;
        }
        
        @Override
        public int compareTo(Engineer other) {
            if (this.e == other.e) {
                return other.s - this.s;
            }
            return other.e - this.e;
        }
    }
    
    public int maxPerformance(int n, int[] speed, int[] efficiency, int k) {
        int i = 0, j = 0;
        long ans = 0;
        Engineer[] engs = new Engineer[n];
        for (i=0; i<n; ++i) {
            engs[i] = new Engineer(speed[i], efficiency[i]);
        }
        Arrays.sort(engs);
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        long sum = 0;
        int size = 0;
        for (Engineer eng: engs) {
            if (size < k) {
                pq.add(eng.s);
                sum += (long) eng.s;
                ++size;
                ans = Math.max(ans, sum * ((long) eng.e));
            } else {
                if (pq.peek() < eng.s) {
                    sum -= (long) pq.poll();
                    pq.add(eng.s);
                    sum += (long) eng.s;
                    ans = Math.max(ans, sum * ((long) eng.e));
                }
            }
        }
        return (int)(ans % mod);
    }
}