跳至主要內容

力扣第 394 场周赛

大约 3 分钟

力扣第 394 场周赛

比赛时间 2024-04-21。本场周赛国服共 647 人 AK。

最近有些断更,实在太忙了,就连今天这一场,赛时也在处理工作相关的事情。。

T1. 统计特殊字母的数量 I(3 分)

解题思路

枚举。

时间复杂度:O(n)

参考代码

class Solution {
    public int numberOfSpecialChars(String word) {
        boolean[] lowercase = new boolean[26];
        boolean[] uppercase = new boolean[26];
        for (char c : word.toCharArray()) {
            if (Character.isLowerCase(c)) {
                lowercase[c - 'a'] = true;
            } else {
                uppercase[c - 'A'] = true;
            }
        }
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            if (lowercase[i] && uppercase[i]) {
                ans++;
            }
        }
        return ans;
    }
}

T2. 统计特殊字母的数量 II(4 分)

解题思路

枚举。

时间复杂度:O(n)

参考代码

class Solution {
    public int numberOfSpecialChars(String word) {
        int n = word.length();
        int[] upper_first = new int[26];
        Arrays.fill(upper_first, -1);
        int[] lower_last = new int[26];
        Arrays.fill(lower_last, n);
        for (int i = 0; i < n; i++) {
            char c = word.charAt(i);
            if (Character.isLowerCase(c)) {
                lower_last[c - 'a'] = i;
            } else {
                if (upper_first[c - 'A'] == -1) {
                    upper_first[c - 'A'] = i;
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < 26; i++) {
            if (lower_last[i] < upper_first[i]) {
                ans++;
            }
        }
        return ans;
    }
}

T3. 使矩阵满足条件的最少操作次数(5 分)

解题思路

记忆化搜索。取 top3 频次对应的数字来做 DP 即可。

时间复杂度:O(mn + nU^2)。其中本题 U = 10

参考代码

class Solution {
    private int m, n;
    private List<Node[]> cntList;
    private int[][] memo;

    public int minimumOperations(int[][] grid) {
        this.m = grid.length;
        this.n = grid[0].length;

        cntList = new ArrayList<>();
        Node[] cnt0 = new Node[3];
        for (int i = 0; i < 3; i++) {
            cnt0[i] = new Node(10, m);
        }
        cntList.add(cnt0);
        for (int j = 0; j < n; j++) {
            Node[] cnt = new Node[11];
            for (int i = 0; i < 11; i++) {
                cnt[i] = new Node(i, 0);
            }
            for (int[] row : grid) {
                cnt[row[j]].cnt++;
            }
            Arrays.sort(cnt, (o1, o2) -> Integer.compare(o2.cnt, o1.cnt));
            cntList.add(cnt);
        }

        memo = new int[n + 1][11];
        for (int i = 0; i < n + 1; i++) {
            Arrays.fill(memo[i], -1);
        }
        return dfs(1, 10);
    }

    private int dfs(int i, int pre) {
        if (i == n + 1) return 0;

        if (memo[i][pre] != -1) return memo[i][pre];
        int res = Integer.MAX_VALUE;
        Node[] cnt = cntList.get(i);
        // 取 top3 即可
        for (int k = 0; k < 3; k++) {
            if (cnt[k].num != pre) {
                res = Math.min(res, m - cnt[k].cnt + dfs(i + 1, cnt[k].num));
            }
        }
        return memo[i][pre] = res;
    }

    private static class Node {
        int num, cnt;

        public Node(int num, int cnt) {
            this.num = num;
            this.cnt = cnt;
        }
    }
}

T4. 最短路径中的边(6 分)

解题思路

最短路 + BFS。

找出需要保留的点。具体就是从 0n-1 出发分别跑一趟 dijkstra,然后在最短路上的带你就是需要保留的。

然后 BFS 处理一下即可。

时间复杂度:O(mlogm + n)

参考代码

class Solution {
    private static final long INF = (long) 1e18;
    private int n;
    private List<int[]>[] g;

    public boolean[] findAnswer(int n, int[][] edges) {
        this.n = n;
        int m = edges.length;
        // y, wt, i
        g = new ArrayList[n];
        Arrays.setAll(g, e -> new ArrayList<>());
        for (int i = 0; i < m; i++) {
            int x = edges[i][0], y = edges[i][1], wt = edges[i][2];
            g[x].add(new int[]{y, wt, i});
            g[y].add(new int[]{x, wt, i});
        }
        long[] dist_st = dijkstra_mlogm(0);
        long[] dist_end = dijkstra_mlogm(n - 1);
        // 需要保留的点
        boolean[] must = new boolean[n];
        for (int i = 0; i < n; i++) {
            if (dist_st[i] + dist_end[i] == dist_st[n - 1]) {
                must[i] = true;
            }
        }

        boolean[] ans = new boolean[m];
        // y, wt
        Queue<long[]> q = new ArrayDeque<>();
        q.add(new long[]{0, 0});
        while (!q.isEmpty()) {
            long[] top = q.remove();
            int x = (int) top[0];
            long d = top[1];
            for (int[] p : g[x]) {
                int y = p[0], wt = p[1], id = p[2];
                if (must[y] && dist_st[y] == wt + d) {
                    ans[id] = true;
                    q.add(new long[]{y, wt + d});
                }
            }
        }
        return ans;
    }

    private long[] dijkstra_mlogm(int st) {
        // y, wt
        PriorityQueue<long[]> pq = new PriorityQueue<>(Comparator.comparingLong(o -> o[1]));
        boolean[] vis = new boolean[n];
        long[] dist = new long[n];
        Arrays.fill(dist, INF);
        pq.add(new long[]{st, 0});
        dist[st] = 0;
        while (!pq.isEmpty()) {
            long[] top = pq.remove();
            int x = (int) top[0];
            if (vis[x]) continue;
            vis[x] = true;
            for (int[] p : g[x]) {
                int y = p[0], wt = p[1];
                if (dist[y] > dist[x] + wt) {
                    dist[y] = dist[x] + wt;
                    pq.add(new long[]{y, dist[y]});
                }
            }
        }
        return dist;
    }
}

(全文完)