From ada737c9c0ee78347f5c53349ae61cdb08943fd1 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Wed, 24 May 2023 23:01:33 +0800 Subject: [PATCH] modify code --- ...de01_LeastNumberOfUniqueAfterRemovals.java | 51 ++++ .../Code02_SplitNtoKMaxProduct.java | 96 ++++++++ .../Code03_ValidateStackSequences.java | 25 ++ .../Code04_EquipmentFirstToEnd.java | 83 +++++++ .../Code05_NetworkDelayGuess.java | 231 ++++++++++++++++++ .../Code06_ConversionOfFinancialProducts.java | 145 +++++++++++ ...养的大厂算法面试题(正在直播) | 114 +++++++++ 7 files changed, 745 insertions(+) create mode 100644 算法周更班/class_2023_05_4_week/Code01_LeastNumberOfUniqueAfterRemovals.java create mode 100644 算法周更班/class_2023_05_4_week/Code02_SplitNtoKMaxProduct.java create mode 100644 算法周更班/class_2023_05_4_week/Code03_ValidateStackSequences.java create mode 100644 算法周更班/class_2023_05_4_week/Code04_EquipmentFirstToEnd.java create mode 100644 算法周更班/class_2023_05_4_week/Code05_NetworkDelayGuess.java create mode 100644 算法周更班/class_2023_05_4_week/Code06_ConversionOfFinancialProducts.java diff --git a/算法周更班/class_2023_05_4_week/Code01_LeastNumberOfUniqueAfterRemovals.java b/算法周更班/class_2023_05_4_week/Code01_LeastNumberOfUniqueAfterRemovals.java new file mode 100644 index 0000000..9fec56a --- /dev/null +++ b/算法周更班/class_2023_05_4_week/Code01_LeastNumberOfUniqueAfterRemovals.java @@ -0,0 +1,51 @@ +package class_2023_05_4_week; + +import java.util.Arrays; +import java.util.HashMap; + +// 先来一个智力题,来自美团面试题 +// 给定n个二维坐标,表示在二维平面的n个点, +// 坐标为double类型,精度最多小数点后两位 +// 希望在二维平面上画一个圆,圈住其中的k个点,其他的n-k个点都要在圆外 +// 返回一个圆心和半径,表示哪个圆可以圈住其中的k个点 +// 坐标和半径都是double类型,最多保留小数点后两位 +// 下面是正式题目 +// 给你一个整数数组 arr 和一个整数 k +// 现需要从数组中恰好移除 k 个元素 +// 请找出移除后数组中不同整数的最少数目 +// 测试链接 : https://leetcode.cn/problems/least-number-of-unique-integers-after-k-removals/ +public class Code01_LeastNumberOfUniqueAfterRemovals { + + public static int findLeastNumOfUniqueInts(int[] arr, int k) { + HashMap map = new HashMap<>(); + for (int num : arr) { + map.put(num, map.getOrDefault(num, 0) + 1); + } + // 2 : 5次 + // 4 : 9次 + // 7 : 2次 + // 5 : 6次 + int n = map.size(); + int[] cnts = new int[n]; + int i = 0; + for (int cnt : map.values()) { + cnts[i++] = cnt; + } + // [5, 9, 2, 6] + // [2, 5, 6, 9] + Arrays.sort(cnts); + for (i = 0; i < n; i++) { + k -= cnts[i]; + if (k <= 0) { + // 该结束了 + if (k == 0) { + // i位置词频,彻底耗费完了 + i++; + } + break; + } + } + return n - i; + } + +} diff --git a/算法周更班/class_2023_05_4_week/Code02_SplitNtoKMaxProduct.java b/算法周更班/class_2023_05_4_week/Code02_SplitNtoKMaxProduct.java new file mode 100644 index 0000000..96a479d --- /dev/null +++ b/算法周更班/class_2023_05_4_week/Code02_SplitNtoKMaxProduct.java @@ -0,0 +1,96 @@ +package class_2023_05_4_week; + +// 来自华为 +// 一个数字n,一定要分成k份 +// 得到的乘积尽量大是多少 +// 数字n和k,可能非常大,到达10^12规模 +// 结果可能更大,所以返回结果对1000000007取模 +public class Code02_SplitNtoKMaxProduct { + + // 暴力递归 + // 一定能得到最优解 + public static int maxValue1(int n, int k) { + if (k == 0 || n < k) { + return -1; + } + return process1(n, k); + } + + // 剩余的数字rest,一定要拆成j份,返回最大乘积 + public static int process1(int rest, int j) { + if (j == 1) { + return rest; + } + // 10 , 3份 + // 1 * f(9,2) + // 2 * f(8,2) + // 3 * f(7,2) + // ... + int ans = Integer.MIN_VALUE; + for (int cur = 1; cur <= rest && (rest - cur) >= (j - 1); cur++) { + int curAns = cur * process1(rest - cur, j - 1); + ans = Math.max(ans, curAns); + } + return ans; + } + + // 贪心的解 + // 这不是最优解,只是展示贪心思路 + public static int maxValue2(int n, int k) { + if (k == 0 || n < k) { + return -1; + } + // 数字n,一定要分k份 + // 每份先得多少,n/k + int a = n / k; + // 有多少份可以升级成a+1 + int b = n % k; + int ans = 1; + for (int i = 0; i < b; i++) { + ans *= a + 1; + } + for (int i = 0; i < k - b; i++) { + ans *= a; + } + return ans; + } + + // 贪心的解 + // 这是最优解 + // 但是如果结果很大,让求余数... + public static int maxValue3(long n, long k) { + if (k == 0 || n < k) { + return -1; + } + int mod = 1000000007; + long a = n / k; + long b = n % k; + long part1 = power(a + 1, b, mod); + long part2 = power(a, k - b, mod); + return (int) (part1 * part2) % mod; + } + + // 返回a的n次方,%mod的结果 + public static long power(long a, long n, int mod) { + long ans = 1; + long tmp = a; + while (n != 0) { + if ((n & 1) != 0) { + ans = (ans * tmp) % mod; + } + n >>= 1; + tmp = (tmp * tmp) % mod; + } + return ans; + } + + public static void main(String[] args) { + // 可以自己来用参数实验 + int n = 20; + int k = 4; + System.out.println(maxValue1(n, k)); + System.out.println(maxValue2(n, k)); +// System.out.println(maxValue3(n, k)); + } + +} diff --git a/算法周更班/class_2023_05_4_week/Code03_ValidateStackSequences.java b/算法周更班/class_2023_05_4_week/Code03_ValidateStackSequences.java new file mode 100644 index 0000000..53d51a0 --- /dev/null +++ b/算法周更班/class_2023_05_4_week/Code03_ValidateStackSequences.java @@ -0,0 +1,25 @@ +package class_2023_05_4_week; + +// 来自美团 +// 给定 pushed 和 popped 两个序列,每个序列中的 值都不重复, +// 只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时, +// 返回 true;否则,返回 false 。 +// 测试链接 : https://leetcode.cn/problems/validate-stack-sequences/ +public class Code03_ValidateStackSequences { + + public boolean validateStackSequences(int[] pushed, int[] popped) { + int n = pushed.length; + int size = 0; + for (int i = 0, j = 0; i < n; i++) { + // i : 入栈数组,哪个位置的数要进栈 + // j : 出栈数组,对比的位置 + pushed[size++] = pushed[i]; + while (size > 0 && j < n && pushed[size - 1] == popped[j]) { + size--; + j++; + } + } + return size == 0; + } + +} diff --git a/算法周更班/class_2023_05_4_week/Code04_EquipmentFirstToEnd.java b/算法周更班/class_2023_05_4_week/Code04_EquipmentFirstToEnd.java new file mode 100644 index 0000000..ac02834 --- /dev/null +++ b/算法周更班/class_2023_05_4_week/Code04_EquipmentFirstToEnd.java @@ -0,0 +1,83 @@ +package class_2023_05_4_week; + +import java.util.ArrayList; +import java.util.PriorityQueue; + +// 来自招商银行 +// 给定一个数组arr,长度为n,表示有0~n-1号设备 +// arr[i]表示i号设备的型号,型号的种类从0~k-1,一共k种型号 +// 给定一个k*k的矩阵map,来表示型号之间的兼容情况 +// map[a][b] == 1,表示a型号兼容b型号 +// map[a][b] == 0,表示a型号不兼容b型号 +// 兼容关系是有向图,也就是a型号兼容b型号,不代表b型号同时兼容a型号 +// 如果i设备的型号兼容j设备的型号,那么可以从i设备修建一条去往j设备的线路 +// 修建线路的代价是i设备到j设备的距离:|i-j| +// 你的目标是从0号设备到达n-1号设备,并不一定每个设备都联通,只需要到达即可 +// 返回最小的修建代价,如果就是无法到达返回-1 +// 1 <= n <= 1000 +// 1 <= k <= 50 +public class Code04_EquipmentFirstToEnd { + + public static int minCost(int[] arr, int[][] map, int n, int k) { + // 0 : {4,7,13,26} + // 1 : {5,45,3,17} + ArrayList> own = new ArrayList<>(); + // 0 1 2 3 + // 0 1 0 1 0 + // 1 0 1 1 0 + // 2 1 1 1 1 + // 3 + // 0 : 0, 2 + // 1 : 1, 2 + // 2 : 0 1 2 3 + ArrayList> nexts = new ArrayList<>(); + for (int i = 0; i < k; i++) { + own.add(new ArrayList<>()); + nexts.add(new ArrayList<>()); + } + for (int i = 0; i < n; i++) { + own.get(arr[i]).add(i); + } + for (int i = 0; i < k; i++) { + for (int j = 0; j < k; j++) { + if (i != j && map[i][j] == 1) { + nexts.get(i).add(j); + } + } + } + // 放入的数据是一个长度为2的数组 + // 0 : 来到的地点号 + // 1 : 距离0号地点有多远(根据代价排序) + // 堆里,小根堆 : {7, 10} + PriorityQueue heap = new PriorityQueue<>((a, b) -> a[1] - b[1]); + heap.add(new int[] { 0, 0 }); + boolean[] visited = new boolean[n]; + while (!heap.isEmpty()) { + int[] cur = heap.poll(); + int position = cur[0]; + int cost = cur[1]; + if (!visited[position]) { + visited[position] = true; + if (position == n - 1) { + return cost; + } + // 你来到了一个地点,拿出型号! + int model = arr[position]; + // 5 : {0,3,5,7} + // 0: .... + // 3: .... + // 5: .... + // 7: .... + for (int nextModel : nexts.get(model)) { + for (int nextPosition : own.get(nextModel)) { + if (!visited[nextPosition]) { + heap.add(new int[] { nextPosition, cost + Math.abs(nextPosition - position) }); + } + } + } + } + } + return -1; + } + +} diff --git a/算法周更班/class_2023_05_4_week/Code05_NetworkDelayGuess.java b/算法周更班/class_2023_05_4_week/Code05_NetworkDelayGuess.java new file mode 100644 index 0000000..207d237 --- /dev/null +++ b/算法周更班/class_2023_05_4_week/Code05_NetworkDelayGuess.java @@ -0,0 +1,231 @@ +package class_2023_05_4_week; + +import java.util.HashSet; + +// 来自招商银行 +// 这个题是个破题,但这可能是经常遇到的一种题, +// 讲一下思路即可,没有必要投入大多时间给这种题目 +// 一共有三个服务A、B、C,网络延时分别为a、b、c +// 并且一定有:1 <= a <= b <= c <= 10^9 +// 但是具体的延时数字丢失了,只有单次调用的时间 +// 一次调用不可能重复使用相同的服务, +// 一次调用可能使用了三个服务中的某1个、某2个或者全部3个服务 +// 比如一个调用的时间,T = 100 +// 100的延时可能来自以下7种情况: +// a = 100,这次调用可能单独使用了A +// b = 100,这次调用可能单独使用了B +// c = 100,这次调用可能单独使用了C +// a + b = 100,这次调用可能组合使用了A、B +// a + c = 100,这次调用可能组合使用了A、C +// b + c = 100,这次调用可能组合使用了B、C +// a + b + c = 100,这次调用可能组合使用了A、B、C全部服务 +// 那么可想而知,如果给的调用时间足够多,是可以猜测出a、b、c的 +// 给定一个数组times,长度为n,并且一定有4 <= n <= 7 +// times[i] = s,表示i号调用用时s,而且times中一定都是正数且没有重复值 +// 请根据n次调用,猜测出a、b、c三元组可能的情况数 +// 如果任何a、b、c都无法匹配上给定的调用耗时,返回0 +// 测试的次数T <= 100 +// 也就是说,一共最多给定100个数组,每一次让你返回a、b、c三元组可能的情况数 +public class Code05_NetworkDelayGuess { + +// public static void zuo() { +// +// // status[0] : a +// // status[1] : b +// // status[2] : c +// // status[3] : a + b +// // status[4] : a + c +// // status[5] : b + c +// // status[6] : a + b + c +// // status[4] = 0, a + c 没被选中! +// // status[4] > 0 , a + c 250 +// int[] status = new int[7]; +// int[] values = { 100, 50, 150, 250 }; +// +// } +// +// public static void test(int[] status, int[] values, int i) { +// if (i == values.length) { +// // 分配之后,a、b、c求出来 +// } else { +// // values[i] : +// for (int j = 0; j < status.length; j++) { +// if (status[j] == 0) { +// status[j] = values[i]; +// test(status, values, i + 1); +// status[j] = 0; +// } +// } +// } +// +// } + + // 这个函数在测试时最多会调用100次,100次的整体运行时间1s以内 + public static int ways(int[] times) { + int[] status = new int[7]; + HashSet ans = new HashSet<>(); + process(times, 0, status, ans); + return ans.size(); + } + + // status[0] : a + // status[1] : b + // status[2] : c + // status[3] : a + b + // status[4] : a + c + // status[5] : b + c + // status[6] : a + b + c + public static void process(int[] times, int i, int[] status, HashSet ans) { + if (i == times.length) { + int a = 0; + int b = 0; + int c = 0; + int cnt = counts(status); + if (cnt == 0) { + a = (status[3] + status[4] - status[5]) / 2; + b = (status[3] + status[5] - status[4]) / 2; + c = (status[4] + status[5] - status[3]) / 2; + } else if (cnt == 1) { + if (status[0] != 0) { + a = status[0]; + if (status[3] != 0) { + b = status[3] - a; + } + if (status[4] != 0) { + c = status[4] - a; + } + if (status[5] != 0) { + if (b != 0 && c == 0) { + c = status[5] - b; + } + if (c != 0 && b == 0) { + b = status[5] - c; + } + } + } else if (status[1] != 0) { + b = status[1]; + if (status[3] != 0) { + a = status[3] - b; + } + if (status[5] != 0) { + c = status[5] - b; + } + if (status[4] != 0) { + if (a != 0 && c == 0) { + c = status[4] - a; + } + if (c != 0 && a == 0) { + a = status[4] - c; + } + } + } else { + c = status[2]; + if (status[4] != 0) { + a = status[4] - c; + } + if (status[5] != 0) { + b = status[5] - c; + } + if (status[3] != 0) { + if (a != 0 && b == 0) { + b = status[3] - a; + } + if (b != 0 && a == 0) { + a = status[3] - b; + } + } + } + } else if (cnt == 2) { + if (status[0] != 0) { + a = status[0]; + } + if (status[1] != 0) { + b = status[1]; + } + if (status[2] != 0) { + c = status[2]; + } + if (a == 0) { + if (status[3] != 0) { + a = status[3] - b; + } else if (status[4] != 0) { + a = status[4] - c; + } else { + a = status[6] - b - c; + } + } else if (b == 0) { + if (status[3] != 0) { + b = status[3] - a; + } else if (status[5] != 0) { + b = status[5] - c; + } else { + b = status[6] - a - c; + } + } else { + if (status[4] != 0) { + c = status[4] - a; + } else if (status[5] != 0) { + c = status[5] - b; + } else { + c = status[6] - a - b; + } + } + } else { + a = status[0]; + b = status[1]; + c = status[2]; + } + if (verify(status, a, b, c)) { + ans.add(a + "_" + b + "_" + c); + } + } else { + for (int j = 0; j < 7; j++) { + if (status[j] == 0) { + status[j] = times[i]; + process(times, i + 1, status, ans); + status[j] = 0; + } + } + } + } + + public static int counts(int[] status) { + int cnt = 0; + for (int i = 0; i < 3; i++) { + if (status[i] != 0) { + cnt++; + } + } + return cnt; + } + + // a <= b <= c + public static boolean verify(int[] s, int a, int b, int c) { + if (a <= 0 || b <= 0 || c <= 0 || a > b || b > c) { + return false; + } + if (s[0] != 0 && s[0] != a) { + return false; + } + if (s[1] != 0 && s[1] != b) { + return false; + } + if (s[2] != 0 && s[2] != c) { + return false; + } + if (s[3] != 0 && s[3] != a + b) { + return false; + } + if (s[4] != 0 && s[4] != a + c) { + return false; + } + if (s[5] != 0 && s[5] != b + c) { + return false; + } + if (s[6] != 0 && s[6] != a + b + c) { + return false; + } + return true; + } + +} diff --git a/算法周更班/class_2023_05_4_week/Code06_ConversionOfFinancialProducts.java b/算法周更班/class_2023_05_4_week/Code06_ConversionOfFinancialProducts.java new file mode 100644 index 0000000..ed5f2d5 --- /dev/null +++ b/算法周更班/class_2023_05_4_week/Code06_ConversionOfFinancialProducts.java @@ -0,0 +1,145 @@ +package class_2023_05_4_week; + +import java.util.ArrayList; +import java.util.Arrays; + +// 来自招商银行 +// 原始题目描述 +// 假如某公司目前推出了N个在售的金融产品(1<=N<=100) +// 对于张三,用ai表示他购买了ai(0<=ai<=10^4)份额的第i个产品(1<=i<=N) +// 现给出K(1<=K<=N)个方案,通过这些方案,能够支持将多个不同的产品进行整合 +// (也可以对单个产品进行优化)形成新的产品。 +// 新的产品形成后,若用户持有了组成新产品所需的全部的原产品份额, +// 则能够将用户持有的原产品份额转换为新产品的份额,各原产品份额与新产品份额比例均为1:1 +// 我们保证对于每个产品最多存在一个方案使用旧产品整合成该产品 +// 并且根据方案产出的新产品的产品编号均大于各旧产品的产品编号 +// 现计划根据这些方案,帮助部分愿意升级到最新产品的用户对产品进行升级 +// 请协助工作人员计算当前用户能够转换出的最新产品份额的最大值 +// 输入描述 +// 第一行包含整数N,第二行包含N个整数ai,第三行包含整数K +// 接下来的K行,每一行代表一个方案,每一行包含整数1和M(M>=1) +// L为该方案产生的新产品的编号,M代表方案所需原产品个数 +// 接下来的M个整数代表了该方案所需的每个原产品的个数 +// 输出描述 +// 根据日前的份额和给出的方案,经过若干次转换,输出当前用户能够得到产品N的份额最大值 +// 举例 +// 输入: +// 5 +// 2 0 0 1 0 +// 3 +// 5 2 3 4 +// 2 1 1 +// 3 1 2 +// 输出: +// 1 +// 解释: +// 第一步将1份1产品转化为1份2产品 +// 第二步将1份2产品转化为1份3产品 +// 第三步将1份3产品和1份4产品,转成为1份5产品 +// 然后不能得到更多的5产品了,所以返回1 +// 实在是太困惑了,上文说的意思可谓不做人,那么我们改写一下意思,变得好理解 +// 如下是改写后的题目描述 +// 给定一个数组arr,长度为n,产品编号从0~n-1 +// arr[i]代表初始时i号产品有多少份 +// 存在一系列的产品转化方案的数组convert,长度为k,代表k个方案 +// 比如具体某一个方案,convert[j] = {a, b, c, d, ...} +// 表示当前的j号方案转化出来的产品是a,转化1份a需要:1份b、1份c、1份d... +// 其中a、b、c、d...一定都在0~n-1范围内 +// 并且题目保证a > Math.max(b, c, d, ....) +// 而且题目保证所有方案转化出来的产品编号一定是不重复的 +// 请返回最终能得到的第n-1号商品的最大值 +// 1 <= n <= 100 +// 0 <= arr[i] <= 10^4 +// k < n +public class Code06_ConversionOfFinancialProducts { + + public static int MAXN = 101; + + public static int[] indegree = new int[MAXN]; + + public static int[] help = new int[MAXN]; + + public static int[] zeroQueue = new int[MAXN]; + + public static int[] need = new int[MAXN]; + + public static int n; + + public static int maxValue(int[] arr, int[][] convert) { + n = arr.length; + ArrayList> graph = new ArrayList<>(); + for (int i = 0; i < n; i++) { + graph.add(new ArrayList<>()); + } + Arrays.fill(indegree, 0, n, 0); + for (int[] relation : convert) { + for (int i = 1; i < relation.length; i++) { + graph.get(relation[0]).add(relation[i]); + indegree[relation[i]]++; + } + } + // arr[n-1] 初始就有100份 + // 101 ~ 整体累加和 + int l = arr[n - 1] + 1; + int r = 0; + for (int num : arr) { + r += num; + } + int m = 0, ans = arr[n - 1]; + while (l <= r) { + m = (l + r) / 2; + if (ok(arr, graph, m)) { + ans = m; + l = m + 1; + } else { + r = m - 1; + } + } + return ans; + } + + // arr里,是每一种商品的初始份额 + // graph就是图,3 -> 0 1 2 + // aim目标,一定要转化出这么多份!n-1号商品 + public static boolean ok(int[] arr, ArrayList> graph, int aim) { + int l = 0; + int r = 0; + for (int i = 0; i < n; i++) { + help[i] = indegree[i]; + if (help[i] == 0) { + zeroQueue[r++] = i; + } + } + Arrays.fill(need, 0, n, 0); + need[n - 1] = aim; + while (l < r) { + // 当前商品的编号! + int cur = zeroQueue[l++]; + // 需要底层给它供应的量 + int supplement = Math.max(need[cur] - arr[cur], 0); + if (graph.get(cur).isEmpty() && supplement > 0) { + return false; + } + for (int next : graph.get(cur)) { + need[next] += supplement; + if (--help[next] == 0) { + zeroQueue[r++] = next; + } + } + } + return true; + } + + public static void main(String[] args) { + int[] arr1 = { 2, 0, 0, 1, 0 }; + int[][] convert1 = { { 4, 2, 3 }, { 1, 0 }, { 2, 1 } }; + System.out.println(maxValue(arr1, convert1)); + + // 我构造了一个非常好的例子 + // 课上说明一下 + int[] arr2 = { 100, 5, 5, 0 }; + int[][] convert2 = { { 1, 0 }, { 2, 0, 1 }, { 3, 0, 1, 2 } }; + System.out.println(maxValue(arr2, convert2)); + } + +} diff --git a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) index 822c0be..3953d78 100644 --- a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) +++ b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) @@ -3675,6 +3675,120 @@ v是中心点,依次打印 : v u o p q w .... +第070节 2023年5月第4周流行算法题目解析 + +先来一个智力题,来自美团面试题 +给定n个二维坐标,表示在二维平面的n个点, +坐标为double类型,精度最多小数点后两位 +希望在二维平面上画一个圆,圈住其中的k个点,其他的n-k个点都要在圆外 +返回一个圆心和半径,表示哪个圆可以圈住其中的k个点 +坐标和半径都是double类型,最多保留小数点后两位 +下面是正式题目 +给你一个整数数组 arr 和一个整数 k +现需要从数组中恰好移除 k 个元素 +请找出移除后数组中不同整数的最少数目 +测试链接 : https://leetcode.cn/problems/least-number-of-unique-integers-after-k-removals/ + +来自华为 +一个数字n,一定要分成k份 +得到的乘积尽量大是多少 +数字n和k,可能非常大,到达10^12规模 +结果可能更大,所以返回结果对1000000007取模 + +来自美团 +给定 pushed 和 popped 两个序列,每个序列中的 值都不重复, +只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时, +返回 true;否则,返回 false 。 +测试链接 : https://leetcode.cn/problems/validate-stack-sequences/ + +来自招商银行 +给定一个数组arr,长度为n,表示有0~n-1号设备 +arr[i]表示i号设备的型号,型号的种类从0~k-1,一共k种型号 +给定一个k*k的矩阵map,来表示型号之间的兼容情况 +map[a][b] == 1,表示a型号兼容b型号 +map[a][b] == 0,表示a型号不兼容b型号 +兼容关系是有向图,也就是a型号兼容b型号,不代表b型号同时兼容a型号 +如果i设备的型号兼容j设备的型号,那么可以从i设备修建一条去往j设备的线路 +修建线路的代价是i设备到j设备的距离:|i-j| +你的目标是从0号设备到达n-1号设备,并不一定每个设备都联通,只需要到达即可 +返回最小的修建代价,如果就是无法到达返回-1 +1 <= n <= 1000 +1 <= k <= 50 + +来自招商银行 +这个题是个破题,但这可能是经常遇到的一种题, +讲一下思路即可,没有必要投入大多时间给这种题目 +一共有三个服务A、B、C,网络延时分别为a、b、c +并且一定有:1 <= a <= b <= c <= 10^9 +但是具体的延时数字丢失了,只有单次调用的时间 +一次调用不可能重复使用相同的服务, +一次调用可能使用了三个服务中的某1个、某2个或者全部3个服务 +比如一个调用的时间,T = 100 +100的延时可能来自以下7种情况: +a = 100,这次调用可能单独使用了A +b = 100,这次调用可能单独使用了B +c = 100,这次调用可能单独使用了C +a + b = 100,这次调用可能组合使用了A、B +a + c = 100,这次调用可能组合使用了A、C +b + c = 100,这次调用可能组合使用了B、C +a + b + c = 100,这次调用可能组合使用了A、B、C全部服务 +那么可想而知,如果给的调用时间足够多,是可以猜测出a、b、c的 +给定一个数组times,长度为n,并且一定有4 <= n <= 7 +times[i] = s,表示i号调用用时s,而且times中一定都是正数且没有重复值 +请根据n次调用,猜测出a、b、c三元组可能的情况数 +如果任何a、b、c都无法匹配上给定的调用耗时,返回0 +测试的次数T <= 100 +也就是说,一共最多给定100个数组,每一次让你返回a、b、c三元组可能的情况数 + +来自招商银行 +原始题目描述 +假如某公司目前推出了N个在售的金融产品(1<=N<=100) +对于张三,用ai表示他购买了ai(0<=ai<=10^4)份额的第i个产品(1<=i<=N) +现给出K(1<=K<=N)个方案,通过这些方案,能够支持将多个不同的产品进行整合 +(也可以对单个产品进行优化)形成新的产品。 +新的产品形成后,若用户持有了组成新产品所需的全部的原产品份额, +则能够将用户持有的原产品份额转换为新产品的份额,各原产品份额与新产品份额比例均为1:1 +我们保证对于每个产品最多存在一个方案使用旧产品整合成该产品 +并且根据方案产出的新产品的产品编号均大于各旧产品的产品编号 +现计划根据这些方案,帮助部分愿意升级到最新产品的用户对产品进行升级 +请协助工作人员计算当前用户能够转换出的最新产品份额的最大值 +输入描述 +第一行包含整数N,第二行包含N个整数ai,第三行包含整数K +接下来的K行,每一行代表一个方案,每一行包含整数1和M(M>=1) +L为该方案产生的新产品的编号,M代表方案所需原产品个数 +接下来的M个整数代表了该方案所需的每个原产品的个数 +输出描述 +根据日前的份额和给出的方案,经过若干次转换,输出当前用户能够得到产品N的份额最大值 +举例 +输入: +5 +2 0 0 1 0 +3 +5 2 3 4 +2 1 1 +3 1 2 +输出: +1 +解释: +第一步将1份1产品转化为1份2产品 +第二步将1份2产品转化为1份3产品 +第三步将1份3产品和1份4产品,转成为1份5产品 +然后不能得到更多的5产品了,所以返回1 +实在是太困惑了,上文说的意思可谓不做人,那么我们改写一下意思,变得好理解 +如下是改写后的题目描述 +给定一个数组arr,长度为n,产品编号从0~n-1 +arr[i]代表初始时i号产品有多少份 +存在一系列的产品转化方案的数组convert,长度为k,代表k个方案 +比如具体某一个方案,convert[j] = {a, b, c, d, ...} +表示当前的j号方案转化出来的产品是a,转化1份a需要:1份b、1份c、1份d... +其中a、b、c、d...一定都在0~n-1范围内 +并且题目保证a > Math.max(b, c, d, ....) +而且题目保证所有方案转化出来的产品编号一定是不重复的 +请返回最终能得到的第n-1号商品的最大值 +1 <= n <= 100 +0 <= arr[i] <= 10^4 +k < n +