G
N
I
D
A
O
L

力扣第 102 场双周赛

题目链接:https://leetcode.cn/contest/biweekly-contest-102/

# T1. 查询网格图中每一列的宽度

链接:https://leetcode.cn/problems/find-the-width-of-columns-of-a-grid/

# 代码

a
class Solution {
    public int[] findColumnWidth(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        
        int[] ans = new int[n];
        
        for (int i = 0; i < n; ++i) {
            int max = 0;
            for (int j = 0; j < m; ++j) {
                int abs = Math.abs(grid[j][i]);
                int l = len(abs);
                l = grid[j][i] < 0 ? l + 1 : l;
                max = Math.max(l, max);
            }
            ans[i] = max;
        }
        
        return ans;
    }
    private int len(int k) {
        if (k == 0) return 1;
        int ret = 0;
        while (k > 0) {
            ++ret;
            k /= 10;
        }
        return ret;
    }
}

# T2. 一个数组所有前缀的分数

链接:https://leetcode.cn/problems/find-the-score-of-all-prefixes-of-an-array/

# 思路

根据题意模拟即可

# 提交结果

image.png

# 代码

a
class Solution {
    public long[] findPrefixScore(int[] nums) {
        int n = nums.length;
        long[] ans = new long[n];
        
        long max = 0;
        
        for (int i = 0; i < n; ++i) {
            max = Math.max(nums[i], max);
            ans[i] = max + nums[i];
            if (i > 0) {
                ans[i] += ans[i - 1];
            } 
        }
        
        return ans;
    }
}

# T3. 二叉树的堂兄弟节点 II

链接:https://leetcode.cn/problems/cousins-in-binary-tree-ii/

# 解题思路

二叉树层序遍历:

  • 记录每个节点的直接父亲节点
  • 根据父亲节点进行分组求和,最后更新左右子节点的值即可

具体看代码

# 提交结果

image.png

# 代码

a
class Solution {
    public TreeNode replaceValueInTree(TreeNode root) {
        if (root == null) return null;
        Queue<TreeNode[]> que = new ArrayDeque<>();
        root.val = 0;
        
        if (root.left != null) {
            que.offer(new TreeNode[] {root, root.left});
        }
        if (root.right != null) {
            que.offer(new TreeNode[] {root, root.right});
        }
        
        while (!que.isEmpty()) {
            Map<TreeNode, Integer> sumMap = new HashMap<>();
            int sum = 0;
            for (int i = que.size(); i > 0; --i) {
                TreeNode[] cur = que.poll();
                sumMap.put(cur[0], sumMap.getOrDefault(cur[0], 0) + cur[1].val);
                sum += cur[1].val;
                if (cur[1].left != null) {
                    que.offer(new TreeNode[] {cur[1], cur[1].left});
                }
                
                if (cur[1].right != null) {
                    que.offer(new TreeNode[] {cur[1], cur[1].right});
                }
                
            }
            
            for (Map.Entry<TreeNode, Integer> e : sumMap.entrySet()) {
                TreeNode node = e.getKey();
                int value = e.getValue();
                int v = sum - value;
                if (node.left != null) {
                    node.left.val = v;
                }
                
                if (node.right != null) {
                    node.right.val = v;
                }
            }
        }
        
        return root;
    }
}

# 优化

不用每次记录当前节点的父节点,而是每次遍历一层时,更新下一层的节点值即可。

a
class Solution {
    public TreeNode replaceValueInTree(TreeNode root) {
        // 在 parent 层,处理 children 层
        if (root == null) return null;
        Queue<TreeNode> que = new ArrayDeque<>();
        // 根节点直接赋值 0
        root.val = 0;
        
        que.offer(root);
        while (!que.isEmpty()) {
            Map<TreeNode, Integer> sumMap = new HashMap<>();
            // 记录所有父节点的所有子节点值的和
            int sum = 0;
            for (TreeNode p : que) {
                sum += p.left != null ? p.left.val : 0;
                sum += p.right != null ? p.right.val : 0;
            }
            
            // 更新父节点的子节点的值
            for (int i = que.size(); i > 0; --i) {
                TreeNode cur = que.poll();
                
                int cs = cur.left != null ? cur.left.val : 0;
                cs += cur.right != null ? cur.right.val : 0;
                
                if (cur.left != null) {
                    cur.left.val = sum - cs;
                    que.offer(cur.left);
                }
                if (cur.right != null) {
                    cur.right.val = sum - cs;
                    que.offer(cur.right);
                }
            }
        }
        return root;
    }
}

# T4. 设计可以求最短路径的图类

链接:https://leetcode.cn/problems/design-graph-with-shortest-path-calculator/

# 解题思路

典型 Dijkstra 算法应用

# 提交结果

image.png

# 代码

a
class Graph {
    // 边的权值:es [i][j] 表示 i -> j,有一条权值 es [i][j] 的有向边
    //es [i][j]=Integer.MAX_VALUE 表示 i -> j 为不可达
    int[][] es;
    // 节点总数
    int nodeCnt;
    public Graph(int n, int[][] edges) {
        es = new int[n][n];
        this.nodeCnt = n;
        
        // 初始化所有点相互之间的距离
        for (int i = 0; i < n; ++i) {
            Arrays.fill(es[i], Integer.MAX_VALUE);
        }
        for (int[] e : edges) {
            es[e[0]][e[1]] = e[2];
        }
    }
    public void addEdge(int[] edge) {
        es[edge[0]][edge[1]] = edge[2];
    }
    public int shortestPath(int node1, int node2) {
        if (node1 == node2) return 0;
        int[] dis = new int[nodeCnt];
        boolean[] vis = new boolean[nodeCnt];
        // 加入集合
        vis[node1] = true;
        // 更新 node1 -> 其他节点的直接距离
        for (int i = 0; i < nodeCnt; ++i) {
            dis[i] = es[node1][i];
        }
        // 最多松弛 nodeCnt - 1 次
        for (int i = 1; i < nodeCnt; ++i) {
            // 到下一个最短路径的点
            int nxt = -1;
            // 到下一个点的最短距离
            int minDis = Integer.MAX_VALUE;
            for (int j = 0; j < nodeCnt; ++j) {
                if (!vis[j] && dis[j] < minDis) {
                    nxt = j;
                    minDis = dis[j];
                }
            }
            // 没有多余的到可达点,直接退出
            // 优化:已经到达终点
            if (nxt == -1 || nxt == node2) break;
            // 找到一个点
            vis[nxt] = true;
            // 松弛操作,通过 nxt 节点
            for (int j = 0; j < nodeCnt; j++) {
                if (!vis[j] // 未加入集合
                        && es[nxt][j] != Integer.MAX_VALUE // 可达
                        && minDis + es[nxt][j] < dis[j]) { // 可松弛,更新最小值
                    dis[j] = minDis + es[nxt][j];
                }
            }
        }
        return dis[node2] == Integer.MAX_VALUE ? -1 : dis[node2];
    }
}
/**
 * Your Graph object will be instantiated and called as such:
 * Graph obj = new Graph(n, edges);
 * obj.addEdge(edge);
 * int param_2 = obj.shortestPath(node1,node2);
 */
更新于 阅读次数

😉觉得写的还不错,请我喝杯咖啡吧😁

独步凌波 微信支付

微信支付

独步凌波 支付宝

支付宝