6333. Find the Width of Columns of a Grid

给你一个下标从 0 开始的 m x n 整数矩阵 grid 。矩阵中某一列的宽度是这一列数字的最大 字符串长度 。

  • 比方说,如果 grid = [[-10], [3], [12]] ,那么唯一一列的宽度是 3 ,因为 -10 的字符串长度为 3 。

请你返回一个大小为 n 的整数数组 ans ,其中 ans[i] 是第 i 列的宽度。

一个有 len 个数位的整数 x ,如果是非负数,那么 字符串长度 为 len ,否则为 len + 1 。

测试样例

输入:grid = [[1],[22],[333]]

输出:[3]

解释:

第 0 列中,333 字符串长度为 3 。

解答:按照题意暴力运算

class Solution {
    public int[] findColumnWidth(int[][] grid) {
        int n = grid[0].length;
        int[] res = new int[n];
        for (int[] r : grid) {
            for (int i = 0; i < n; ++i) {
                res[i] = Math.max(res[i], String.valueOf(r[i]).length());
            }
        }
        return res;
    }
}

6334. Find the Score of All Prefixes of an Array

定义一个数组 arr 的 转换数组 conver 为:

  • conver[i] = arr[i] + max(arr[0..i]),其中 max(arr[0..i]) 是满足 0 <= j <= i 的所有 arr[j] 中的最大值。

定义一个数组 arr 的 分数 为 arr 转换数组中所有元素的和。

给你一个下标从 0 开始长度为 n 的整数数组 nums ,请你返回一个长度为 n 的数组 ans ,其中 ans[i]是前缀 nums[0..i] 的分数。

测试样例:

输入:nums = [2,3,7,5,10]

输出:[4,10,24,36,56]

解释:

  • 对于前缀 [2] ,转换数组为 [4] ,所以分数为 4 。
  • 对于前缀 [2, 3] ,转换数组为 [4, 6] ,所以分数为 10 。
  • 对于前缀 [2, 3, 7] ,转换数组为 [4, 6, 14] ,所以分数为 24 。
  • 对于前缀 [2, 3, 7, 5] ,转换数组为 [4, 6, 14, 12] ,所以分数为 36 。
  • 对于前缀 [2, 3, 7, 5, 10] ,转换数组为 [4, 6, 14, 12, 20] ,所以分数为 56 。

解答: 计算前缀最大值,然后按照题意累和一下。注意结果是long[], int[]会超范围

class Solution {
    public long[] findPrefixScore(int[] nums) {
        long[] res = new long[nums.length];
        long sum = 0;
        int max = -1;
        for (int i = 0; i < nums.length; ++i) {
            max = Math.max(max, nums[i]);
            long tmp = nums[i];
            tmp += max;
            sum += tmp;
            res[i] = sum;
        }
        return res;
    }
}

6335. Cousins in Binary Tree II

给你一棵二叉树的根 root ,请你将每个节点的值替换成该节点的所有 堂兄弟节点值的和 。

如果两个节点在树中有相同的深度且它们的父节点不同,那么它们互为 堂兄弟 。

请你返回修改值之后,树的根 root 。

注意,一个节点的深度指的是从树根节点到这个节点经过的边数。

测试样例:

输入:root = [5,4,9,1,10,null,7]

输出:[0,0,0,7,7,null,11]

解答: 这道题目本质是树的层次遍历。在纯粹的层次遍历过程中,加入一层的累和,同时也需要记录每个节点的父节点。最后在更新原树的时候,把当堂兄弟的和减去

class Solution {
    private class TreeNodeParent {
        TreeNode node;
        TreeNode parent;

        public TreeNodeParent(TreeNode _node, TreeNode _parent) {
            node = _node;
            parent = _parent;
        }
    }

    public TreeNode replaceValueInTree(TreeNode root) {
        List<TreeNodeParent> mem = new ArrayList<>();
        mem.add(new TreeNodeParent(root, new TreeNode(0)));
        while(!mem.isEmpty()) {
            List<TreeNodeParent> next = new ArrayList<>();
            HashMap<TreeNode, Integer> add = new HashMap<>();
            int sum = 0;
            for (TreeNodeParent p : mem) {
                sum += p.node.val;
                add.put(p.parent, add.getOrDefault(p.parent, 0) + p.node.val);
                if (p.node.left != null) {
                    next.add(new TreeNodeParent(p.node.left, p.node));
                }
                if (p.node.right != null) {
                    next.add(new TreeNodeParent(p.node.right, p.node));
                }
            }

            for (TreeNodeParent p : mem) {
                p.node.val = sum - add.get(p.parent);
            }
            mem = next;
        }
        return root;
    }
}

6336. Design Graph With Shortest Path Calculator

给你一个有 n 个节点的 有向带权 图,节点编号为 0 到 n - 1 。图中的初始边用数组 edges 表示,其中 edges[i] = [fromi, toi, edgeCosti] 表示从 fromi 到 toi 有一条代价为 edgeCosti 的边。

请你实现一个 Graph 类:

  • Graph(int n, int[][] edges) 初始化图有 n 个节点,并输入初始边。
  • addEdge(int[] edge) 向边集中添加一条边,其中 edge = [from, to, edgeCost] 。数据保证添加这条边之前对应的两个节点之间没有有向边。
  • int shortestPath(int node1, int node2) 返回从节点 node1 到 node2 的路径 最小 代价。如果路径不存在,返回 -1 。一条路径的代价是路径中所有边代价之和。

测试样例:

输入:["Graph", "shortestPath", "shortestPath", "addEdge", "shortestPath"]
[[4, [[0, 2, 5], [0, 1, 2], [1, 2, 1], [3, 0, 3]]], [3, 2], [0, 3], [[1, 3, 4]], [0, 3]]

输出:[null, 6, -1, null, 6]

解答:这道题目有3个很重要的提示:

  • 1 <= n <= 100
  • 调用 addEdge 至多 100 次
  • 调用 shortestPath 至多 100 次

这个规模可以每次调用shortestPath,用Dijstrak算法跑一下最小值就行了

class Graph {
    private List<int[]>[] map;

    public Graph(int n, int[][] edges) {
        map = new List[n];
        for (int i = 0; i < n; ++i) {
            map[i] = new ArrayList<>();
        }
        for (int[] e : edges) {
            map[e[0]].add(e);
        }
    }

    public void addEdge(int[] e) {
        map[e[0]].add(e);
    }

    public int shortestPath(int node1, int node2) {
        int[] mem = new int[map.length];
        Arrays.fill(mem, Integer.MAX_VALUE);
        mem[node1] = 0;
        TreeSet<Integer> queue = new TreeSet<>((a, b) -> (mem[a] != mem[b] ? (mem[a] - mem[b]) : (a - b)));
        queue.add(node1);
        while (!queue.isEmpty()) {
            int first = queue.first();
            queue.remove(first);
            if (first == node2) {
                return mem[node2];
            }
            int lastCost = mem[first];
            for (int[] e : map[first]) {
                if (lastCost + e[2] < mem[e[1]]) {
                    queue.remove(e[1]);
                    mem[e[1]] = lastCost + e[2];
                    queue.add(e[1]);
                }
            }
        }
        return -1;
    }
}

这周的题目,又是究极手速场了。最后一道题目蹲一个大佬非暴力算法

Leave a Reply

Your email address will not be published. Required fields are marked *