[Leetcode Weekly Contest]314

链接:LeetCode

[Leetcode]2432. 处理用时最长的那个任务的员工

共有 n 位员工,每位员工都有一个从 0 到 n - 1 的唯一 id 。
给你一个二维整数数组 logs ,其中 logs[i] = [idi, leaveTimei] :

  • idi 是处理第 i 个任务的员工的 id ,且
  • leaveTimei 是员工完成第 i 个任务的时刻。所有 leaveTimei 的值都是 唯一 的。

注意,第 i 个任务在第 (i - 1) 个任务结束后立即开始,且第 0 个任务从时刻 0 开始。
返回处理用时最长的那个任务的员工的 id 。如果存在两个或多个员工同时满足,则返回几人中 最小 的 id 。

遍历即可。

class Solution {
    public int hardestWorker(int n, int[][] logs) {
        int mxWorker = logs[0][1];
        int res = logs[0][0];
        for(int i=1;i<logs.length;++i) {
            int useTime = logs[i][1] - logs[i-1][1];
            if(useTime == mxWorker) res = Math.min(res, logs[i][0]);
            if(useTime > mxWorker) {
                mxWorker = useTime;
                res = logs[i][0];
            }
        }
        return res;
    }
}

[Leetcode]2433. 找出前缀异或的原始数组

给你一个长度为 n 的 整数 数组 pref 。找出并返回满足下述条件且长度为 n 的数组 arr :
pref[i] = arr[0] ^ arr[1] ^ ... ^ arr[i].
注意 ^ 表示 按位异或(bitwise-xor)运算。
可以证明答案是 唯一 的。

问题本质上是给你前缀和,还原回原数组。
由于前缀和的差分是原数组,因此直接两两异或即可。

class Solution {
    public int[] findArray(int[] pref) {
        int n = pref.length;
        int[] res = new int[n];
        res[0] = pref[0];
        for(int i=1;i<n;++i) {
            res[i] = pref[i-1] ^ pref[i];
        }
        return res;
    }
}

[Leetcode]2434. 使用机器人打印字典序最小的字符串

给你一个字符串 s 和一个机器人,机器人当前有一个空字符串 t 。执行以下操作之一,直到 s 和 t 都变成空字符串:

  • 删除字符串 s 的 第一个 字符,并将该字符给机器人。机器人把这个字符添加到 t 的尾部。
  • 删除字符串 t 的 最后一个 字符,并将该字符给机器人。机器人将该字符写到纸上。

请你返回纸上能写出的字典序最小的字符串。

贪心模拟。难点是需要记录每次弹出字符后,后续可能会出现的最小字符。
我们首先将题目描述进行转化:有一个初始为空的栈,给定字符的入栈顺序,求字典序最小的出栈序列。
当一个字符入栈后,我们持续检查栈顶元素 c。设还未入栈的字符中,字典序最小的字符是 m,有以下两种情况。

  • \(c \le m\):此时弹出 cc 最优。如果此时按兵不动,下一个出栈的将会是大等于 c 的字符,答案不会变优。
  • \(c > m\):此时不弹出 c,等待后续更小的字符入栈。

所有字符都入栈后,栈内的剩余字符按顺序弹出即可。复杂度 \(\mathcal{O}(n)\)

class Solution {
    public String robotWithString(String s) {
        int n = s.length();
        int[] f = new int[n+1];
        f[n] = 26;
        for(int i=n-1;i>=0;--i) f[i] = Math.min(f[i+1], s.charAt(i) - 'a');

        ArrayDeque<Character> queue = new ArrayDeque<>();
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<n;++i) {
            queue.push(s.charAt(i));
            while(!queue.isEmpty() && queue.peek()-'a' <= f[i+1])
                sb.append(queue.poll());
        }
        return sb.toString();

    }
}

[Leetcode] 2435. 矩阵中和能被 K 整除的路径

给你一个下标从 0 开始的 m x n 整数矩阵 grid 和一个整数 k 。你从起点 (0, 0) 出发,每一步只能往 下 或者往 右 ,你想要到达终点 (m - 1, n - 1) 。
请你返回路径和能被 k 整除的路径数目,由于答案可能很大,返回答案对 \(10^9 + 7\) 取余 的结果。

二维动态规划,dp[i][j][t]表示到[i, j]处路径和余k为t的路径数目
状态转移方程为dp[i + 1][j + 1][(grid[i][j] + t) % k] = (dp[i][j + 1][t] + dp[i + 1][j][t]) % mod,但是要判断数组下标是否越界

class Solution {
    private int MODE = (int)1e9 + 7;
    public int numberOfPaths(int[][] grid, int num) {
        int n = grid.length, m = grid[0].length;
        int[][][] dp = new int[n+1][m+1][num];
        for(int i=1;i<n+1;++i) {
            for(int j=1;j<m+1;++j) {
                if(i == 1 && j == 1) {
                    dp[1][1][grid[0][0] % num] = 1;
                    continue;
                }
                int mod = grid[i-1][j-1] % num;
                for(int k=0;k<num;++k) {
                    int need = (k+num-mod) % num;
                    dp[i][j][k] = (dp[i-1][j][need] + dp[i][j-1][need]) % MODE;
                }
            }
        }
        return dp[n][m][0];
    }
}
posted @ 2022-10-12 20:24  Jamest  阅读(19)  评论(0编辑  收藏  举报