Leetcode周赛394

100294. 统计特殊字母的数量 I

解法一

将小写字母放到一个集合中,将大写字母变成小写字母放到另一个集合中,取两个集合之间的交集。

class Solution {
    public int numberOfSpecialChars(String word) {
        Set<Character> lowercaseSet = new HashSet<>();
        Set<Character> uppercaseSet = new HashSet<>();
         for (char c : word.toCharArray()) {
            if (Character.isLowerCase(c)) {

                lowercaseSet.add(c);
            } else if (Character.isUpperCase(c)) {
   
                uppercaseSet.add(Character.toLowerCase(c));
            }
        }
        Set<Character> intersection = new HashSet<>(lowercaseSet);
         intersection.retainAll(uppercaseSet); /
        return intersection.size();
    }
}
解法二

位运算,大写字母和小写字母的区别,在于8位中第三为一个是0一个是1, 后五位表示是什么字母。

  1. ASCII >> 5 & 1 判断是小写还是大写

  2. ASCII & 31 取这个字母是第几个字母

  3. 通过位运算往集合里面添加元素 |= 1 << i

  4. 集合求交集 A & B

  5. 集合求大小 Integer.bitCount()

    class Solution {
        public int numberOfSpecialChars(String word) {
            
            int[] mask = new int[2];
            for (char c : word.toCharArray()) {
                mask[c >> 5 & 1] |= 1 << (c & 31);
            }
            return Integer.bitCount(mask[0] & mask[1]);
    
        }
    }
    

100291. 统计特殊字母的数量 II

解法一

模拟

class Solution {
    public int numberOfSpecialChars(String word) {
        int ans = 0;
        int[] state = new int[27];
        for (char c : word.toCharArray()) {
            int x = c & 31; // 转成数字 1~26
            if ((c & 32) > 0) { // 小写字母
                if (state[x] == 0) {
                    state[x] = 1;
                } else if (state[x] == 2) {
                    state[x] = -1;
                    ans--;
                }
            } else { // 大写字母
                if (state[x] == 0) {
                    state[x] = -1;
                } else if (state[x] == 1) {
                    state[x] = 2;
                    ans++;
                }
            }
        }
        return ans;
    }
}

解法二

位运算, 创建一个小写集合,大写集合,非法集合。如果在小写字母判断中发现已经存在大写集合中,则加入非法集合,最后判断小写集合和大写集合的交集并且没在非法集合的元素。

1. 元素是否在集合中 bit & A > 0
1. 元素在A中 ,不能在B中 *A*&∼*B*
class Solution {
    public int numberOfSpecialChars(String word) {
        int lower=0,upper=0, invalid=0;
        for(char c :word.toCharArray()){
            int  bit = 1 << (c&31);
            if( (c >> 5 & 1) == 1){
                lower |= bit;
                if((upper & bit) > 0){
                    invalid |= bit;
                }
            }else{
                upper |= bit;
            }
        }
        return Integer.bitCount(lower & upper & ~invalid);
    }
}

100290. 使矩阵满足条件的最少操作次数

将操作最少的元素改为保留最多的元素,最后才进行减去

class Solution {
    public int minimumOperations(int[][] grid) {
        int m = grid.length, n= grid[0].length;
        int f0 = 0, f1 = 0, pre = -1;
        for(int i=0;i<n;i++){
            int[] cnt  = new int[10];
            // 统计每行的元素
            for(int[] row:grid){
                cnt[row[i]]++;
            }
            // 本列的最大值 和次大值, 以及选取的元素  
            int mx = -1, mx2 =0, x = -1;

            for(int v=0;v<10;v++){
                int res = (v!=pre?f0:f1) + cnt[v];
                if(res>mx){
                    mx2 = mx;
                    mx = res;
                    x = v;
                }else if(res>mx2){
                    mx2 = res;
                }
            }

            f0 = mx;
            f1 = mx2;
            pre = x;

        }
        return m*n -f0;
    }
}

3123. 最短路径中的边

如何保证找到的边一定在从0出发的最短路上?

dis[x] + w(x, y) = dis[y]

如何保证找到的边一定在从0到n-1的最短路上,倒着出发

dis[x] + w(x,y) = dis[y]

将边进行构图

   List<int[]>[] g = new ArrayList[n];
        Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < edges.length; i++) {
            int[] e = edges[i];
            int x = e[0], y = e[1], w = e[2];
            g[x].add(new int[]{y, w, i});
            g[y].add(new int[]{x, w, i});
        }

Dijkstra算法模板

long[] dis = new long[n];
        Arrays.fill(dis, Long.MAX_VALUE);
        dis[0] = 0;
        PriorityQueue<long[]> pq = new PriorityQueue<>((a, b) -> Long.compare(a[0], b[0]));
        pq.offer(new long[]{0, 0});
        while (!pq.isEmpty()) {
            long[] dxPair = pq.poll();
            long dx = dxPair[0];
            int x = (int) dxPair[1];
            if (dx > dis[x]) {
                continue;
            }
            for (int[] t : g[x]) {
                int y = t[0];
                int w = t[1];
                long newDis = dx + w;
                if (newDis < dis[y]) {
                    dis[y] = newDis;
                    pq.offer(new long[]{newDis, y});
                }
            }
        }

整体

class Solution {
    public boolean[] findAnswer(int n, int[][] edges) {
        List<int[]>[] g = new ArrayList[n];
        Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < edges.length; i++) {
            int[] e = edges[i];
            int x = e[0], y = e[1], w = e[2];
            g[x].add(new int[]{y, w, i});
            g[y].add(new int[]{x, w, i});
        }

        long[] dis = new long[n];
        Arrays.fill(dis, Long.MAX_VALUE);
        dis[0] = 0;
        PriorityQueue<long[]> pq = new PriorityQueue<>((a, b) -> Long.compare(a[0], b[0]));
        pq.offer(new long[]{0, 0});
        while (!pq.isEmpty()) {
            long[] dxPair = pq.poll();
            long dx = dxPair[0];
            int x = (int) dxPair[1];
            if (dx > dis[x]) {
                continue;
            }
            for (int[] t : g[x]) {
                int y = t[0];
                int w = t[1];
                long newDis = dx + w;
                if (newDis < dis[y]) {
                    dis[y] = newDis;
                    pq.offer(new long[]{newDis, y});
                }
            }
        }

        boolean[] ans = new boolean[edges.length];
        // 图不连通
        if (dis[n - 1] == Long.MAX_VALUE) {
            return ans;
        }

        // 从终点出发 DFS
        boolean[] vis = new boolean[n];
        dfs(n - 1, g, dis, ans, vis);
        return ans;
    }

    private void dfs(int y, List<int[]>[] g, long[] dis, boolean[] ans, boolean[] vis) {
        vis[y] = true;
        for (int[] t : g[y]) {
            int x = t[0];
            int w = t[1];
            int i = t[2];
            if (dis[x] + w != dis[y]) {
                continue;
            }
            ans[i] = true;
            if (!vis[x]) {
                dfs(x, g, dis, ans, vis);
            }
        }
    }
}