VP

6208. 有效时间的数目

显示英文描述
我的提交返回竞赛

  • 通过的用户数2686
  • 尝试过的用户数2790
  • 用户总通过次数2721
  • 用户总提交次数7089
  • 题目难度Easy

给你一个长度为 5 的字符串 time ,表示一个电子时钟当前的时间,格式为 “hh:mm” 。最早 可能的时间是 “00:00” ,最晚 可能的时间是 “23:59” 。
在字符串 time 中,被字符 ? 替换掉的数位是 未知的 ,被替换的数字可能是 0 到 9 中的任何一个。
请你返回一个整数 _answer ,将每一个 ? 都用 0 到 _9 中一个数字替换后,可以得到的有效时间的数目。

示例 1:
输入:time = “?5:00” 输出:2 解释:我们可以将 ? 替换成 0 或 1 ,得到 “05:00” 或者 “15:00” 。注意我们不能替换成 2 ,因为时间 “25:00” 是无效时间。所以我们有两个选择。
示例 2:
输入:time = “0?:0?” 输出:100 解释:两个 ? 都可以被 0 到 9 之间的任意数字替换,所以我们总共有 100 种选择。
示例 3:
输入:time = “??:??” 输出:1440 解释:小时总共有 24 种选择,分钟总共有 60 种选择。所以总共有 24 * 60 = 1440 种选择。

提示:

  • time 是一个长度为 5 的有效字符串,格式为 “hh:mm” 。
  • “00” <= hh <= “23”
  • “00” <= mm <= “59”
  • 字符串中有的数位是 ‘?’ ,需要用 0 到 9 之间的数字替换。

思路:回溯 check

  1. class Solution {
  2. public int countTime(String time) {
  3. return dfs(time, 0, "");
  4. }
  5. int dfs(String s, int u, String t) {
  6. if (u == 5) {
  7. if (check(t))
  8. return 1;
  9. else return 0;
  10. }
  11. if (s.charAt(u) != '?') return dfs(s, u + 1, t + s.charAt(u));
  12. else {
  13. int res = 0;
  14. for (char c = '0'; c <= '9'; c++) {
  15. res += dfs(s, u + 1, t + c);
  16. }
  17. return res;
  18. }
  19. }
  20. boolean check(String s) {
  21. int h = (s.charAt(0) - '0') * 10 + s.charAt(1) - '0';
  22. int m = (s.charAt(3) - '0') * 10 + s.charAt(4) - '0';
  23. return h >= 0 && h <= 23 && m >= 0 && m <= 59;
  24. }
  25. }

6209. 二的幂数组中查询范围内的乘积

显示英文描述
我的提交返回竞赛

  • 通过的用户数1976
  • 尝试过的用户数2316
  • 用户总通过次数2016
  • 用户总提交次数5933
  • 题目难度Medium

给你一个正整数 n ,你需要找到一个下标从 0 开始的数组 powers ,它包含 最少 数目的 2 的幂,且它们的和为 n 。powers 数组是 非递减 顺序的。根据前面描述,构造 powers 数组的方法是唯一的。
同时给你一个下标从 0 开始的二维整数数组 queries ,其中 queries[i] = [lefti, righti] ,其中 queries[i] 表示请你求出满足 lefti <= j <= righti 的所有 powers[j] 的乘积。
请你返回一个数组 _answers ,长度与 queries 的长度相同,其中 answers[i]是第 _i 个查询的答案。由于查询的结果可能非常大,请你将每个 answers[i] 都对 109 + 7 取余

示例 1:
输入:n = 15, queries = [[0,1],[2,2],[0,3]] 输出:[2,4,64] 解释: 对于 n = 15 ,得到 powers = [1,2,4,8] 。没法得到元素数目更少的数组。 第 1 个查询的答案:powers[0] powers[1] = 1 2 = 2 。 第 2 个查询的答案:powers[2] = 4 。 第 3 个查询的答案:powers[0] powers[1] powers[2] powers[3] = 1 2 4 8 = 64 。 每个答案对 109 + 7 得到的结果都相同,所以返回 [2,4,64] 。
示例 2:
输入:n = 2, queries = [[0,0]] 输出:[2] 解释: 对于 n = 2, powers = [2] 。 唯一一个查询的答案是 powers[0] = 2 。答案对 109 + 7 取余后结果相同,所以返回 [2] 。

提示:

  • 1 <= n <= 109
  • 1 <= queries.length <= 105
  • 0 <= starti <= endi < powers.length

思路:数乘转换为指数相加

  1. class Solution {
  2. public int[] productQueries(int n, int[][] q) {
  3. int m = Integer.bitCount(n);
  4. int[] a = new int[m];
  5. for (int i = 0; i < m; i++) {
  6. for (int j = 0; j < 31; j++) {
  7. if ((n >> j & 1) == 1) {
  8. a[i] = j;
  9. n ^= 1 << j;
  10. break;
  11. }
  12. }
  13. }
  14. // System.out.println(Arrays.toString(a));
  15. int[] p = new int[m + 1];
  16. for (int i = 1; i <= m; i++) {
  17. p[i] = p[i - 1] + a[i - 1];
  18. }
  19. int[] res = new int[q.length];
  20. for (int i = 0; i < q.length; i++) {
  21. int l = q[i][0], r = q[i][1];
  22. res[i] = pow(2, p[r + 1] - p[l]);
  23. }
  24. return res;
  25. }
  26. int pow(long x, int c) {
  27. long res = 1;
  28. int MOD = (int)(1e9 + 7);
  29. while (c > 0) {
  30. if ((c & 1) == 1)
  31. res = (res * x) % MOD;
  32. x = (x * x) % MOD;
  33. c >>= 1;
  34. }
  35. return (int) res;
  36. }
  37. }

6210. 最小化数组中的最大值

显示英文描述
我的提交返回竞赛

  • 通过的用户数1028
  • 尝试过的用户数1963
  • 用户总通过次数1083
  • 用户总提交次数5104
  • 题目难度Medium

给你一个下标从 0 开始的数组 nums ,它含有 n 个非负整数。
每一步操作中,你需要:

  • 选择一个满足 1 <= i < n 的整数 i ,且 nums[i] > 0 。
  • 将 nums[i] 减 1 。
  • 将 nums[i - 1] 加 1 。

你可以对数组执行 任意 次上述操作,请你返回可以得到的 nums 数组中 最大值 最小 为多少。

示例 1:
输入:nums = [3,7,1,6] 输出:5 解释: 一串最优操作是: 1. 选择 i = 1 ,nums 变为 [4,6,1,6] 。 2. 选择 i = 3 ,nums 变为 [4,6,2,5] 。 3. 选择 i = 1 ,nums 变为 [5,5,2,5] 。 nums 中最大值为 5 。无法得到比 5 更小的最大值。 所以我们返回 5 。
示例 2:
输入:nums = [10,1] 输出:10 解释: 最优解是不改动 nums ,10 是最大值,所以返回 10 。

提示:

  • n == nums.length
  • 2 <= n <= 105
  • 0 <= nums[i] <= 109

思路:二分

  1. class Solution {
  2. public int minimizeArrayValue(int[] nums) {
  3. int l = 0, r = (int)(1e9);
  4. while (l < r) {
  5. int mid = l + r >> 1;
  6. if (check(mid, nums))
  7. r = mid;
  8. else l = mid + 1;
  9. }
  10. return l;
  11. }
  12. boolean check(int x, int[] nums) {
  13. long s = 0;
  14. for (int i = nums.length - 1; i >= 0; i--) {
  15. if (nums[i] <= x)
  16. s = Math.max(0, s - (x - nums[i]));
  17. else s += nums[i] - x;
  18. }
  19. return s == 0;
  20. }
  21. }

6211. 创建价值相同的连通块

有一棵 n 个节点的无向树,节点编号为 0 到 n - 1 。
给你一个长度为 n 下标从 0 开始的整数数组 nums ,其中 nums[i] 表示第 i 个节点的值。同时给你一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 与 bi 之间有一条边。
你可以 删除 一些边,将这棵树分成几个连通块。一个连通块的 价值 定义为这个连通块中 所有 节点 i 对应的 nums[i] 之和。
你需要删除一些边,删除后得到的各个连通块的价值都相等。请返回你可以删除的边数 最多 为多少。

示例 1:
image.png
输入:nums = [6,2,2,2,6], edges = [[0,1],[1,2],[1,3],[3,4]] 输出:2 解释:上图展示了我们可以删除边 [0,1] 和 [3,4] 。得到的连通块为 [0] ,[1,2,3] 和 [4] 。每个连通块的价值都为 6 。可以证明没有别的更好的删除方案存在了,所以答案为 2 。
示例 2:
输入:nums = [2], edges = [] 输出:0 解释:没有任何边可以删除。

提示:

  • 1 <= n <= 2 * 104
  • nums.length == n
  • 1 <= nums[i] <= 50
  • edges.length == n - 1
  • edges[i].length == 2
  • 0 <= edges[i][0], edges[i][1] <= n - 1
  • edges 表示一棵合法的树。

思路:考虑每条边将整棵树分成两部分的最大公因子,再一次枚举总和的所有因子,判断边数能否满足要求

  1. class Solution {
  2. final int N = 20010;
  3. int[] h = new int[N], e = new int[2 * N], ne = new int[2 * N];
  4. Map<Integer, Integer> map = new HashMap<>();
  5. int idx = 0, s = 0;
  6. int[] nums;
  7. public int componentValue(int[] nums, int[][] edges) {
  8. Arrays.fill(h, -1);
  9. this.nums = nums;
  10. for (int[] p : edges) {
  11. int a = p[0], b = p[1];
  12. add(a, b);
  13. add(b, a);
  14. }
  15. for (int x : nums) {
  16. s += x;
  17. }
  18. dfs(0, -1);
  19. for (int i = 1; i <= s; i++) {
  20. if (s % i != 0 || s / i > nums.length) continue;
  21. int c = 0, j = i;
  22. while (j <= s) {
  23. c += map.getOrDefault(j, 0);
  24. j += i;
  25. }
  26. if (c >= s / i - 1) {
  27. return s / i - 1;
  28. }
  29. }
  30. return 0;
  31. }
  32. int dfs(int u, int p) {
  33. int res = nums[u];
  34. for (int i = h[u]; i != -1; i = ne[i]) {
  35. int j = e[i];
  36. if (j == p) continue;
  37. int x = dfs(j, u);
  38. res += x;
  39. map.merge(gcd(s-x, x), 1, Integer::sum);
  40. }
  41. return res;
  42. }
  43. void add(int a, int b) {
  44. e[idx] = b;
  45. ne[idx] = h[a];
  46. h[a] = idx++;
  47. }
  48. int gcd(int a, int b) {
  49. return b == 0 ? a : gcd(b, a % b);
  50. }
  51. }