20200827:2020力扣第33周双周赛题解

题目一

题目一:千位分隔数

给你一个整数 n,请你每隔三位添加点(即 “.” 符号)作为千位分隔符,并将结果以字符串格式返回。

示例

示例 1:

输入:n = 987
输出:“987”

示例 2:

输入:n = 1234
输出:“1.234”

示例 3:

输入:n = 123456789
输出:“123.456.789”

解题思路与代码实现

本题直接模拟即可,如果使用栈来实现最好从最后面开始,因为我们拿到的数字不一定是3的倍数。

class Solution {
    
    
    public String thousandSeparator(int n) {
    
    
        String m = String.valueOf(n);
        int len = m.length();
        StringBuilder sb = new StringBuilder();
        int cnt = 0;
        for (int i = len - 1; i >= 0; i--) {
    
    
            sb.append(m.charAt(i));
            cnt++;
            if (cnt % 3 == 0 && i != 0) {
    
    
                sb.append(".");
            }
        }
        return sb.reverse().toString();
    }
}

题目二

题目二:可以到达所有点的最少点数目

给你一个 有向无环图 , n 个节点编号为 0 到 n-1 ,以及一个边数组 edges ,其中 edges[i] = [fromi, toi] 表示一条从点 fromi 到点 toi 的有向边。

找到最小的点集使得从这些点出发能到达图中所有点。题目保证解存在且唯一。

你可以以任意顺序返回这些节点编号。

示例

在这里插入图片描述
在这里插入图片描述

解题思路与代码实现

本题的题意即是获取当前入度为0的所有点的并集即可。

class Solution {
    
    
    public List<Integer> findSmallestSetOfVertices(int n, List<List<Integer>> edges) {
    
    
        // 统计入度为0的点即可
        List<Integer> ans = new ArrayList<Integer>();
        int[] inDegree = new int[n];
        for (List<Integer> edge : edges) {
    
    
            inDegree[edge.get(1)]++;
        }

        for (int i = 0; i < n; i++) {
    
    
            if (inDegree[i] == 0) {
    
    
                ans.add(i);
            }
        }
        return ans;
    }

}

题目三

题目三:得到目标数组的最少函数调用次数
在这里插入图片描述

给你一个与 nums 大小相同且初始值全为 0 的数组 arr ,请你调用以上函数得到整数数组 nums 。

请你返回将 arr 变成 nums 的最少函数调用次数。

答案保证在 32 位有符号整数以内。
在这里插入图片描述

解题思路与代码实现

class Solution {
    
    
    
    int oddCnt = 0;
    int evenCnt = 0;
    
    public int minOperations(int[] nums) {
    
    
        
        int ans = 0;
        for (int num : nums) {
    
    
            numCnt(num);
        }
        ans = oddCnt + evenCnt;
        return ans;
    }

    private void numCnt(int n){
    
    
        int cnt = 0;
        while (n > 0) {
    
    
            if (n % 2 == 1) {
    
    
                oddCnt++;
                n--;
            }
            else {
    
    
                cnt++;
                n /= 2;
            }
        }
        evenCnt = Math.max(evenCnt,cnt);
    }
}

题目四

题目四:二维网格图中探测环

给你一个二维字符网格数组 grid ,大小为 m x n ,你需要检查 grid 中是否存在 相同值 形成的环。

一个环是一条开始和结束于同一个格子的长度 大于等于 4 的路径。对于一个给定的格子,你可以移动到它上、下、左、右四个方向相邻的格子之一,可以移动的前提是这两个格子有 相同的值 。

同时,你也不能回到上一次移动时所在的格子。比方说,环 (1, 1) -> (1, 2) -> (1, 1) 是不合法的,因为从 (1, 2) 移动到 (1, 1) 回到了上一次移动时的格子。

如果 grid 中有相同值形成的环,请你返回 true ,否则返回 false 。

示例

在这里插入图片描述
在这里插入图片描述

解题思路与代码实现

本题dfs半天做不出来,参考了大佬@xiaoxi666的题解,下面附上并查集的题解

class Solution {
    
    
                        
    public boolean containsCycle(char[][] grid) {
    
    
        int h = grid.length;
        int w = grid[0].length;
        DSU dsu = new DSU(w * h);
        for (int i = 0; i < h; ++i) {
    
    
            for (int j = 0; j < w; ++j) {
    
    
                char cur = grid[i][j];
                // 向右搜索
                if (j + 1 < w && cur == grid[i][j + 1]) {
    
    
                    if (dsu.union(i * w + j, i * w + j + 1)) {
    
    
                        return true;
                    }
                }
                // 向下搜索
                if (i + 1 < h && cur == grid[i + 1][j]) {
    
    
                    if (dsu.union(i * w + j, (i + 1) * w + j)) {
    
    
                        return true;
                    }
                }
            }
        }
        return false;
    }


    class DSU {
    
    
        int[] parent;

        public DSU(int N) {
    
    
            parent = new int[N];
            for (int i = 0; i < N; ++i) {
    
    
                parent[i] = i;
            }
        }

        public int find(int x) {
    
    
            if (parent[x] != x) {
    
    
                parent[x] = find(parent[x]);
            }
            return parent[x];
        }

        /**
         * 若合并前,x和y的parent相同,则表示形成环,返回true。
         *
         * @param x
         * @param y
         * @return
         */
        public boolean union(int x, int y) {
    
    
            int parentX = find(x);
            int parentY = find(y);
            if (parentX == parentY) {
    
    
                return true;
            }
            if (parentX < parentY) {
    
    
                parent[parentY] = parentX;
            } else {
    
    
                parent[parentX] = parentY;
            }
            return false;
        }
    }
}



写在最后

一切都很不确定,但坚持学习是必须要做的事,加油!

猜你喜欢

转载自blog.csdn.net/qq_36828395/article/details/108270961