From 6ce50f1ca1a646ee5f88ccbebeeed242dde71b3b Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Thu, 27 Apr 2023 14:06:31 +0800 Subject: [PATCH] modify code --- ...de01_LongestNoDecreaseModifyKSubarray.java | 117 +++++++++++++++++ .../Code02_MinScoreTriangulationPolygon.java | 59 +++++++++ .../Code03_MinOpToMakeElementsEqual.java | 57 ++++++++ .../Code04_MagicScrollProbelm.java | 122 ++++++++++++++++++ .../Code05_ValidRangeBetweenTwoArrays.java | 116 +++++++++++++++++ .../Code06_CollectCoinsInTree.java | 69 ++++++++++ ...养的大厂算法面试题(正在直播) | 77 +++++++++++ 7 files changed, 617 insertions(+) create mode 100644 算法周更班/class_2023_04_4_week/Code01_LongestNoDecreaseModifyKSubarray.java create mode 100644 算法周更班/class_2023_04_4_week/Code02_MinScoreTriangulationPolygon.java create mode 100644 算法周更班/class_2023_04_4_week/Code03_MinOpToMakeElementsEqual.java create mode 100644 算法周更班/class_2023_04_4_week/Code04_MagicScrollProbelm.java create mode 100644 算法周更班/class_2023_04_4_week/Code05_ValidRangeBetweenTwoArrays.java create mode 100644 算法周更班/class_2023_04_4_week/Code06_CollectCoinsInTree.java diff --git a/算法周更班/class_2023_04_4_week/Code01_LongestNoDecreaseModifyKSubarray.java b/算法周更班/class_2023_04_4_week/Code01_LongestNoDecreaseModifyKSubarray.java new file mode 100644 index 0000000..2ab909e --- /dev/null +++ b/算法周更班/class_2023_04_4_week/Code01_LongestNoDecreaseModifyKSubarray.java @@ -0,0 +1,117 @@ +package class_2023_04_4_week; + +// 来自学员问题,蓝桥杯练习题 +// 给定一个长度为n的数组arr +// 现在你有一次机会, 将其中连续的K个数全修改成任意一个值 +// 请你计算如何修改可以使修改后的数 列的最长不下降子序列最长 +// 请输出这个最长的长度。 +// 最长不下降子序列:子序列中的每个数不小于在它之前的数 +// 1 <= k, n <= 10^5 +// 1 <= arr[i] <= 10^6 +// 测试链接 : https://www.luogu.com.cn/problem/P8776 +// 请同学们务必参考如下代码中关于输入、输出的处理 +// 这是输入输出处理效率很高的写法 +// 提交以下的所有代码,并把主类名改成"Main" +// 可以直接通过 +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StreamTokenizer; + +public class Code01_LongestNoDecreaseModifyKSubarray { + + public static int MAXN = 100001; + + public static int[] arr = new int[MAXN]; + + public static int[] right = new int[MAXN]; + + public static int[] ends = new int[MAXN]; + + public static int n, k; + + public static void main(String[] args) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + StreamTokenizer in = new StreamTokenizer(br); + PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); + while (in.nextToken() != StreamTokenizer.TT_EOF) { + n = (int) in.nval; + in.nextToken(); + k = (int) (in.nval); + for (int i = 1; i <= n; i++) { + in.nextToken(); + arr[i] = (int) in.nval; + } + if (k >= n) { + out.println(n); + } else { + right(); + out.println(getAns()); + } + out.flush(); + } + } + + public static void right() { + right[n] = 1; + ends[1] = arr[n]; + int len = 1; + for (int i = n - 1; i > 0; i--) { + int l = 1; + int r = len; + int m, find = len + 1; + while (l <= r) { + m = (l + r) / 2; + if (ends[m] < arr[i]) { + find = m; + r = m - 1; + } else { + l = m + 1; + } + } + ends[find] = arr[i]; + len = Math.max(len, find); + right[i] = find; + } + } + + public static int getAns() { + int ans = 0; + int len = 0; + for (int i = k + 1, j = 1; i <= n; i++, j++) { + int l = 1; + int r = len; + int m, find = len + 1; + while (l <= r) { + m = (l + r) / 2; + // 当前的arr[i], 利用之前的ends,求左边长度! + if (ends[m] > arr[i]) { + find = m; + r = m - 1; + } else { + l = m + 1; + } + } + ans = Math.max(ans, find + right[i] - 1 + k); + l = 1; + r = len; + find = len + 1; + while (l <= r) { + m = (l + r) / 2; + if (ends[m] > arr[j]) { + find = m; + r = m - 1; + } else { + l = m + 1; + } + } + len = Math.max(len, find); + ends[find] = arr[j]; + } + ans = Math.max(ans, len + k); + return ans; + } + +} \ No newline at end of file diff --git a/算法周更班/class_2023_04_4_week/Code02_MinScoreTriangulationPolygon.java b/算法周更班/class_2023_04_4_week/Code02_MinScoreTriangulationPolygon.java new file mode 100644 index 0000000..2dc5813 --- /dev/null +++ b/算法周更班/class_2023_04_4_week/Code02_MinScoreTriangulationPolygon.java @@ -0,0 +1,59 @@ +package class_2023_04_4_week; + +// 开心一下的智力题 : +// 有一个村庄,一共250人 +// 每一个村民要么一定说谎,要么只说真话 +// 村里有A、B、C、D四个球队,且每个村民只会喜欢其中的一支球队 +// 但是说谎者会不告知真实喜好,而且会说是另外三支球队的支持者 +// 访问所有的村民之后,得到的访谈结果如下 : +// A的支持者有90 +// B的支持者有100 +// C的支持者有80 +// D的支持者有80 +// 问村里有多少个说谎者 +// 下面是正式题 : +// 你有一个凸的 n 边形,其每个顶点都有一个整数值。给定一个整数数组 values , +// 其中 values[i] 是第 i 个顶点的值(即 顺时针顺序 )。 +// 假设将多边形 剖分 为 n - 2 个三角形。 +// 对于每个三角形,该三角形的值是顶点标记的乘积, +// 三角剖分的分数是进行三角剖分后所有 n - 2 个三角形的值之和。 +// 返回 多边形进行三角剖分后可以得到的最低分 。 +// 测试链接 : https://leetcode.cn/problems/minimum-score-triangulation-of-polygon/ +public class Code02_MinScoreTriangulationPolygon { + + public static int minScoreTriangulation(int[] values) { + int[][] dp = new int[values.length][values.length]; + for (int i = 0; i < values.length; i++) { + for (int j = 0; j < values.length; j++) { + dp[i][j] = -1; + } + } + return f(values, 0, values.length - 1, dp); + } + + // values[i...j]范围上这些点,要分解成多个三角形 + // 三角形一个端点是values[i],另一个端点是values[j] + // 那么第三个点在i+1....j-1之间选 + // 比如选了m点 : i......m.......j + // 当前获得的分数为values[i] * values[m] * values[j] + // 接下来,i.....m去分解三角形、m.....j去分解三角形 + public static int f(int[] values, int i, int j, int[][] dp) { + if (i >= j - 1) { + // 不够三个点,不会有得分 + return 0; + } + if (dp[i][j] != -1) { + // 缓存的答案 + // 如果命中直接返回 + // 看体系学习班,动态规划的章节 + return dp[i][j]; + } + int ans = Integer.MAX_VALUE; + for (int m = i + 1; m < j; m++) { + ans = Math.min(ans, f(values, i, m, dp) + f(values, m, j, dp) + values[i] * values[m] * values[j]); + } + dp[i][j] = ans; + return ans; + } + +} diff --git a/算法周更班/class_2023_04_4_week/Code03_MinOpToMakeElementsEqual.java b/算法周更班/class_2023_04_4_week/Code03_MinOpToMakeElementsEqual.java new file mode 100644 index 0000000..84f41eb --- /dev/null +++ b/算法周更班/class_2023_04_4_week/Code03_MinOpToMakeElementsEqual.java @@ -0,0 +1,57 @@ +package class_2023_04_4_week; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// 给你一个正整数数组nums, 同时给你一个长度为 m 的整数数组 queries +// 第 i 个查询中,你需要将 nums 中所有元素变成 queries[i] 。你可以执行以下操作 任意 次: +// 将数组里一个元素 增大 或者 减小 1 。请你返回一个长度为 m 的数组 answer , +// 其中 answer[i]是将 nums 中所有元素变成 queries[i] 的 最少 操作次数。 +// 注意,每次查询后,数组变回最开始的值。 +// 测试链接 : https://leetcode.cn/problems/minimum-operations-to-make-all-array-elements-equal/ +public class Code03_MinOpToMakeElementsEqual { + + public static List minOperations(int[] nums, int[] queries) { + int n = nums.length; + Arrays.sort(nums); + long[] sum = new long[n + 1]; + for (int i = 0; i < n; i++) { + sum[i + 1] = sum[i] + nums[i]; + } + ArrayList ans = new ArrayList<>(); + int less, more; + long curAns; + for (int v : queries) { + less = bs(nums, v); + curAns = (long) (less + 1) * v - sum(sum, 0, less); + more = bs(nums, v + 1); + curAns += sum(sum, more + 1, n - 1) - (long) (n - more - 1) * v; + ans.add(curAns); + } + return ans; + } + + // 查找 r ? 0 : (sum[r + 1] - sum[l]); + } + +} diff --git a/算法周更班/class_2023_04_4_week/Code04_MagicScrollProbelm.java b/算法周更班/class_2023_04_4_week/Code04_MagicScrollProbelm.java new file mode 100644 index 0000000..7ac66a3 --- /dev/null +++ b/算法周更班/class_2023_04_4_week/Code04_MagicScrollProbelm.java @@ -0,0 +1,122 @@ +package class_2023_04_4_week; + +// 来自微众银行 +// 两个魔法卷轴问题 +// 给定一个数组arr,其中可能有正、负、0, +// 一个魔法卷轴可以把arr中连续的一段全变成0,你希望数组整体的累加和尽可能大 +// 你有两个魔法卷轴,请返回数组尽可能大的累加和 +// 1 <= arr长度 <= 100000 +// -100000 <= arr里的值 <= 100000 +public class Code04_MagicScrollProbelm { + + // 暴力方法 + // 为了测试 + public static int maxSum1(int[] arr) { + int p1 = 0; + for (int num : arr) { + p1 += num; + } + int n = arr.length; + int p2 = mustOneScroll(arr, 0, n - 1); + int p3 = Integer.MIN_VALUE; + for (int i = 1; i < n; i++) { + p3 = Math.max(p3, mustOneScroll(arr, 0, i - 1) + mustOneScroll(arr, i, n - 1)); + } + return Math.max(p1, Math.max(p2, p3)); + } + + // 为了测试 + public static int mustOneScroll(int[] arr, int L, int R) { + int ans = Integer.MIN_VALUE; + for (int a = L; a <= R; a++) { + for (int b = a; b <= R; b++) { + int curAns = 0; + for (int i = L; i < a; i++) { + curAns += arr[i]; + } + for (int i = b + 1; i <= R; i++) { + curAns += arr[i]; + } + ans = Math.max(ans, curAns); + } + } + return ans; + } + + // 正式方法 + // 时间复杂度O(N) + public static int maxSum2(int[] arr) { + if (arr.length == 0) { + return 0; + } + // 一个卷轴也不用 + int p1 = 0; + for (int num : arr) { + p1 += num; + } + int n = arr.length; + // left[i] : 0 ~ i范围上,一定要用一次卷轴的情况下,最大累加和多少 + int[] left = new int[n]; + // left[0] = 0 : 0 ~ 0,一定要用一次卷轴的情况下,最大累加和多少 + // 每一步的前缀和 + // 0~0 前缀和 + int sum = arr[0]; + // 之前所有前缀和的,最大值 + int maxSum = Math.max(0, sum); + for (int i = 1; i < n; i++) { + // left[i - 1] + arr[i] + // maxSum : 之前所有前缀和的,最大值 + left[i] = Math.max(left[i - 1] + arr[i], maxSum); + sum += arr[i]; + maxSum = Math.max(maxSum, sum); + } + // 只用一次卷轴,必须用,0~n-1范围上的解,第二种可能性 + int p2 = left[n - 1]; + // 第三种 :一定要用两次卷轴 + int[] right = new int[n]; + // right[i] : i ~ n-1范围上,一定要用一次卷轴的情况下,最大累加和多少 + sum = arr[n - 1]; + maxSum = Math.max(0, sum); + for (int i = n - 2; i >= 0; i--) { + right[i] = Math.max(arr[i] + right[i + 1], maxSum); + sum += arr[i]; + maxSum = Math.max(maxSum, sum); + } + int p3 = Integer.MIN_VALUE; + for (int i = 1; i < n; i++) { + // 0..0 1...n-1 + // 0..1 2...n-1 + // 0..2 3...n-1 + p3 = Math.max(p3, left[i - 1] + right[i]); + } + return Math.max(p1, Math.max(p2, p3)); + } + + // 为了测试 + public static int[] randomArray(int n, int v) { + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + ans[i] = (int) (Math.random() * (v * 2 + 1)) - v; + } + return ans; + } + + // 为了测试 + public static void main(String[] args) { + int N = 50; + int V = 100; + int testTimes = 10000; + System.out.println("测试开始"); + for (int i = 0; i < testTimes; i++) { + int n = (int) (Math.random() * N); + int[] arr = randomArray(n, V); + int ans1 = maxSum1(arr); + int ans2 = maxSum2(arr); + if (ans1 != ans2) { + System.out.println("出错了!"); + } + } + System.out.println("测试结束"); + } + +} diff --git a/算法周更班/class_2023_04_4_week/Code05_ValidRangeBetweenTwoArrays.java b/算法周更班/class_2023_04_4_week/Code05_ValidRangeBetweenTwoArrays.java new file mode 100644 index 0000000..7c086fe --- /dev/null +++ b/算法周更班/class_2023_04_4_week/Code05_ValidRangeBetweenTwoArrays.java @@ -0,0 +1,116 @@ +package class_2023_04_4_week; + +// 来自微众银行 +// 给出两个长度均为n的数组 +// A = { a1, a2, ... ,an } +// B = { b1, b2, ... ,bn }。 +// 你需要求出其有多少个区间[L,R]满足: +// 数组A中下标在[L,R]中的元素之和在[La,Ra]之中 +// 数组B中下标在[L,R]中的元素之和在[Lb,Rb]之中 +// 输入 +// 第一行有一个正整数N(1<=N<=100000),代表两个数组的长度。 +// 第二行有N个非负整数,范围在0到1000000000之间,代表数组中的元素。 +// 第三行有N个非负整数,范围在0到1000000000之间,代表数组中的元素。 +// 第四行有4个整数La,Ra,Lb,Rb,范围在0到10^18之间,代表题目描述中的参数。 +// 输出 +// 输出一个整数,代表所求的答案。 +public class Code05_ValidRangeBetweenTwoArrays { + + // 暴力方法 + // 为了测试 + public static int nums1(int[] A, int[] B, int la, int ra, int lb, int rb) { + int n = A.length; + int ans = 0; + for (int l = 0; l < n; l++) { + for (int r = l; r < n; r++) { + int sumA = 0; + int sumB = 0; + for (int i = l; i <= r; i++) { + sumA += A[i]; + sumB += B[i]; + } + if (sumA >= la && sumA <= ra && sumB >= lb && sumB <= rb) { + ans++; + } + } + } + return ans; + } + + // 正式方法 + // 时间复杂度O(N) + public static int nums2(int[] A, int[] B, int la, int ra, int lb, int rb) { + int n = A.length; + int ans = 0; + int rightA1 = 0, sumA1 = 0, rightA2 = 0, sumA2 = 0, rightB1 = 0, sumB1 = 0, rightB2 = 0, sumB2 = 0; + for (int l = 0; l < n; l++) { + while (rightA1 < n && sumA1 + A[rightA1] < la) { + sumA1 += A[rightA1++]; + } + while (rightA2 < n && sumA2 + A[rightA2] <= ra) { + sumA2 += A[rightA2++]; + } + while (rightB1 < n && sumB1 + B[rightB1] < lb) { + sumB1 += B[rightB1++]; + } + while (rightB2 < n && sumB2 + B[rightB2] <= rb) { + sumB2 += B[rightB2++]; + } + int left = Math.max(rightA1, rightB1); + int right = Math.min(rightA2, rightB2); + if (left < right) { + ans += right - left; + } + if (rightA1 == l) { + rightA1++; + } else { + sumA1 -= A[l]; + } + sumA2 -= A[l]; + if (rightB1 == l) { + rightB1++; + } else { + sumB1 -= B[l]; + } + sumB2 -= B[l]; + } + return ans; + } + + // 为了测试 + public static int[] randomArray(int n, int v) { + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + ans[i] = (int) (Math.random() * v); + } + return ans; + } + + // 为了测试 + public static void main(String[] args) { + int N = 50; + int V = 100; + int testTimes = 10000; + System.out.println("测试开始"); + for (int i = 0; i < testTimes; i++) { + int n = (int) (Math.random() * N); + int[] A = randomArray(n, V); + int[] B = randomArray(n, V); + int a = (int) (Math.random() * V); + int b = (int) (Math.random() * V); + int c = (int) (Math.random() * V); + int d = (int) (Math.random() * V); + int la = Math.min(a, b); + int ra = Math.max(a, b); + int lb = Math.min(c, d); + int rb = Math.max(c, d); + int ans1 = nums1(A, B, la, ra, lb, rb); + int ans2 = nums2(A, B, la, ra, lb, rb); + if (ans1 != ans2) { + System.out.println("出错了!"); + } + } + System.out.println("测试结束"); + } + +} diff --git a/算法周更班/class_2023_04_4_week/Code06_CollectCoinsInTree.java b/算法周更班/class_2023_04_4_week/Code06_CollectCoinsInTree.java new file mode 100644 index 0000000..01f04ba --- /dev/null +++ b/算法周更班/class_2023_04_4_week/Code06_CollectCoinsInTree.java @@ -0,0 +1,69 @@ +package class_2023_04_4_week; + +import java.util.ArrayList; + +// 给你一个 n 个节点的无向无根树,节点编号从 0 到 n - 1 +// 给你整数 n 和一个长度为 n - 1 的二维整数数组 edges , +// 其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。 +// 再给你一个长度为 n 的数组 coins ,其中 coins[i] 可能为 0 也可能为 1 , +// 1 表示节点 i 处有一个金币。 +// 一开始,你需要选择树中任意一个节点出发。你可以执行下述操作任意次: +// 收集距离当前节点距离为 2 以内的所有金币,或者 移动到树中一个相邻节点。 +// 你需要收集树中所有的金币,并且回到出发节点,请你返回最少经过的边数。 +// 如果你多次经过一条边,每一次经过都会给答案加一。 +// 测试链接 : https://leetcode.cn/problems/collect-coins-in-a-tree/ +public class Code06_CollectCoinsInTree { + + public static int collectTheCoins(int[] coins, int[][] edges) { + int n = coins.length; + ArrayList> graph = new ArrayList<>(); + int[] inDegree = new int[n]; + for (int i = 0; i < n; i++) { + graph.add(new ArrayList<>()); + } + for (int[] edge : edges) { + // 8 - 13 + graph.get(edge[0]).add(edge[1]); + graph.get(edge[1]).add(edge[0]); + inDegree[edge[0]]++; + inDegree[edge[1]]++; + } + int[] queue = new int[n]; + int l = 0, r = 0; + for (int i = 0; i < n; ++i) { + if (inDegree[i] == 1 && coins[i] == 0) { + queue[r++] = i; + } + } + while (l < r) { + int cur = queue[l++]; + for (int next : graph.get(cur)) { + if (--inDegree[next] == 1 && coins[next] == 0) { + queue[r++] = next; + } + } + } + for (int i = 0; i < n; ++i) { + if (inDegree[i] == 1 && coins[i] == 1) { + queue[r++] = i; + } + } + int[] rank = new int[n]; + while (l < r) { + int cur = queue[l++]; + for (int next : graph.get(cur)) { + if (--inDegree[next] == 1) { + rank[next] = rank[cur] + 1; + queue[r++] = next; + } + } + } + int ans = 0; + for (int[] edge : edges) + if (rank[edge[0]] >= 2 && rank[edge[1]] >= 2) { + ans += 2; + } + return ans; + } + +} diff --git a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) index 430b222..68d3575 100644 --- a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) +++ b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) @@ -3473,5 +3473,82 @@ subtexti == subtextk - i + 1 表示所有 i 的有效值( 即 1 <= i <= k ) +第067节 2023年4月第4周流行算法题目解析 + +(因为上节课网络卡顿,所以这节课安排重讲) +来自学员问题,蓝桥杯练习题 +给定一个长度为n的数组arr +现在你有一次机会, 将其中连续的K个数全修改成任意一个值 +请你计算如何修改可以使修改后的数 列的最长不下降子序列最长 +请输出这个最长的长度。 +最长不下降子序列:子序列中的每个数不小于在它之前的数 +1 <= k, n <= 10^5 +1 <= arr[i] <= 10^6 +测试链接 : https://www.luogu.com.cn/problem/P8776 + +开心一下的智力题 : +有一个村庄,一共250人 +每一个村民要么一定说谎,要么只说真话 +村里有A、B、C、D四个球队,且每个村民只会喜欢其中的一支球队 +但是说谎者会不告知真实喜好,而且会说是另外三支球队的支持者(全支持另外三支球队) +访问所有的村民之后,得到的访谈结果如下 : +A的支持者有90 +B的支持者有100 +C的支持者有80 +D的支持者有80 +问村里有多少个说谎者 +下面是正式题 : +你有一个凸的 n 边形,其每个顶点都有一个整数值。给定一个整数数组 values , +其中 values[i] 是第 i 个顶点的值(即 顺时针顺序 )。 +假设将多边形 剖分 为 n - 2 个三角形。 +对于每个三角形,该三角形的值是顶点标记的乘积, +三角剖分的分数是进行三角剖分后所有 n - 2 个三角形的值之和。 +返回 多边形进行三角剖分后可以得到的最低分 。 +测试链接 : https://leetcode.cn/problems/minimum-score-triangulation-of-polygon/ + +给你一个正整数数组nums, 同时给你一个长度为 m 的整数数组 queries +第 i 个查询中,你需要将 nums 中所有元素变成 queries[i] 。你可以执行以下操作 任意 次: +将数组里一个元素 增大 或者 减小 1 。请你返回一个长度为 m 的数组 answer , +其中 answer[i]是将 nums 中所有元素变成 queries[i] 的 最少 操作次数。 +注意,每次查询后,数组变回最开始的值。 +测试链接 : https://leetcode.cn/problems/minimum-operations-to-make-all-array-elements-equal/ + +来自微众银行 +两个魔法卷轴问题 +给定一个数组arr,其中可能有正、负、0, +一个魔法卷轴可以把arr中连续的一段全变成0,你希望数组整体的累加和尽可能大 +你有两个魔法卷轴,请返回数组尽可能大的累加和 +1 <= arr长度 <= 100000 +-100000 <= arr里的值 <= 100000 + +来自微众银行 +给出两个长度均为n的数组 +A = { a1, a2, ... ,an } +B = { b1, b2, ... ,bn }。 +你需要求出其有多少个区间[L,R]满足: +数组A中下标在[L,R]中的元素之和在[La,Ra]之中 +数组B中下标在[L,R]中的元素之和在[Lb,Rb]之中 +输入 +第一行有一个正整数N(1<=N<=100000),代表两个数组的长度。 +第二行有N个非负整数,范围在0到1000000000之间,代表数组中的元素。 +第三行有N个非负整数,范围在0到1000000000之间,代表数组中的元素。 +第四行有4个整数La,Ra,Lb,Rb,范围在0到10^18之间,代表题目描述中的参数。 +输出 +输出一个整数,代表所求的答案 + +给你一个 n 个节点的无向无根树,节点编号从 0 到 n - 1 +给你整数 n 和一个长度为 n - 1 的二维整数数组 edges , +其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间有一条边。 +再给你一个长度为 n 的数组 coins ,其中 coins[i] 可能为 0 也可能为 1 , +1 表示节点 i 处有一个金币。 +一开始,你需要选择树中任意一个节点出发。你可以执行下述操作任意次: +收集距离当前节点距离为 2 以内的所有金币,或者 移动到树中一个相邻节点。 +你需要收集树中所有的金币,并且回到出发节点,请你返回最少经过的边数。 +如果你多次经过一条边,每一次经过都会给答案加一。 +测试链接 : https://leetcode.cn/problems/collect-coins-in-a-tree/ + + + +