From 23816fe570dae5150b6823f9dc4f83d21e56e0b4 Mon Sep 17 00:00:00 2001 From: algorithmzuo Date: Wed, 24 Aug 2022 23:10:42 +0800 Subject: [PATCH] modify code --- .../Code01_MaxXFromStock.java | 28 +++ .../Code02_ChangeToSame.java | 110 ++++++++++ .../Code03_FindPosition.java | 125 ++++++++++++ .../Code04_MaxPalindromeNumber.java | 93 +++++++++ .../Code05_TravelMinFuel.java | 85 ++++++++ .../Code06_MinCostMostE.java | 192 ++++++++++++++++++ ...养的大厂算法面试题(正在直播) | 94 +++++++++ 7 files changed, 727 insertions(+) create mode 100644 算法周更班/class_2022_08_4_week/Code01_MaxXFromStock.java create mode 100644 算法周更班/class_2022_08_4_week/Code02_ChangeToSame.java create mode 100644 算法周更班/class_2022_08_4_week/Code03_FindPosition.java create mode 100644 算法周更班/class_2022_08_4_week/Code04_MaxPalindromeNumber.java create mode 100644 算法周更班/class_2022_08_4_week/Code05_TravelMinFuel.java create mode 100644 算法周更班/class_2022_08_4_week/Code06_MinCostMostE.java diff --git a/算法周更班/class_2022_08_4_week/Code01_MaxXFromStock.java b/算法周更班/class_2022_08_4_week/Code01_MaxXFromStock.java new file mode 100644 index 0000000..81af0a1 --- /dev/null +++ b/算法周更班/class_2022_08_4_week/Code01_MaxXFromStock.java @@ -0,0 +1,28 @@ +package class_2022_08_4_week; + +// 来自神策 +// 给定一个数组arr,表示连续n天的股价,数组下标表示第几天 +// 指标X:任意两天的股价之和 - 此两天间隔的天数 +// 比如 +// 第3天,价格是10 +// 第9天,价格是30 +// 那么第3天和第9天的指标X = 10 + 30 - (9 - 3) = 34 +// 返回arr中最大的指标X +// 时间复杂度O(N) +public class Code01_MaxXFromStock { + + public static int maxX(int[] arr) { + if (arr == null || arr.length < 2) { + return -1; + } + // 0 + arr[0] + int preBest = arr[0]; + int ans = 0; + for (int i = 1; i < arr.length; i++) { + ans = Math.max(ans, arr[i] - i + preBest); + preBest = Math.max(preBest, arr[i] + i); + } + return ans; + } + +} diff --git a/算法周更班/class_2022_08_4_week/Code02_ChangeToSame.java b/算法周更班/class_2022_08_4_week/Code02_ChangeToSame.java new file mode 100644 index 0000000..21394d2 --- /dev/null +++ b/算法周更班/class_2022_08_4_week/Code02_ChangeToSame.java @@ -0,0 +1,110 @@ +package class_2022_08_4_week; + +// 来自美团 +// 8.20笔试 +// 小团生日收到妈妈送的两个一模一样的数列作为礼物! +// 他很开心的把玩,不过不小心没拿稳将数列摔坏了! +// 现在他手上的两个数列分别为A和B,长度分别为n和m。 +// 小团很想再次让这两个数列变得一样。他现在能做两种操作: +// 操作一是将一个选定数列中的某一个数a改成数b,这会花费|b-a|的时间, +// 操作二是选择一个数列中某个数a,将它从数列中丢掉,花费|a|的时间。 +// 小团想知道,他最少能以多少时间将这两个数列变得再次相同! +// 输入描述: +// 第一行两个空格隔开的正整数n和m,分别表示数列A和B的长度。 +// 接下来一行n个整数,分别为A1 A2…An +// 接下来一行m个整数,分别为B1 B2…Bm +// 对于所有数据,1 ≤ n,m ≤ 2000, |Ai|,|Bi| ≤ 10000 +// 输出一行一个整数,表示最少花费时间,来使得两个数列相同。 +public class Code02_ChangeToSame { + + // A B + // zuo(A,B,0,0) + // A[ai.....] 对应 B[bi.....] + // 请变一样 + // 返回最小代价 + public static int zuo(int[] A, int[] B, int ai, int bi) { + if (ai == A.length && bi == B.length) { + return 0; + } + if (ai != A.length && bi == B.length) { + return A[ai] + zuo(A, B, ai + 1, bi); + } + if (ai == A.length && bi != B.length) { + return B[bi] + zuo(A, B, ai, bi + 1); + } + // A[ai] 有数 B[bi] 有数 + // 可能性1 : 删掉A[ai] + int p1 = A[ai] + zuo(A, B, ai + 1, bi); + // 可能性2 : 删掉B[bi] + int p2 = B[bi] + zuo(A, B, ai, bi + 1); + // 可能性3 : 同时删掉 + // int p3 = A[ai] + B[bi] + zuo(A, B, ai + 1, bi + 1); + // 可能性4 : 变!A[ai] -> B[bi] B[bi] -> A[ai] + int p4 = Math.abs(A[ai] - B[bi]) + zuo(A, B, ai + 1, bi + 1); + // 可能性5 : A[ai] == B[bi] + return Math.min(p1, Math.min(p2, p4)); + } + + public static int minCost(int[] A, int[] B) { + int n = A.length; + int m = B.length; + int[][] dp = new int[n + 1][m + 1]; + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= m; j++) { + dp[i][j] = -1; + } + } + return change(A, B, 0, 0, dp); + } + + // 暴力递归 + // A[indexA....]和B[indexB....]完全一样 + // 需要付出最少的代价返回 + public static int change(int[] A, int[] B, int indexA, int indexB) { + if (indexA == A.length && indexB == B.length) { + return 0; + } + if (indexA == A.length && indexB != B.length) { + return B[indexB] + change(A, B, indexA, indexB + 1); + } + if (indexA != A.length && indexB == B.length) { + return A[indexA] + change(A, B, indexA + 1, indexB); + } + // indexA、indexB都没到最后 + // 可能性1,丢掉A[indexA] + int p1 = A[indexA] + change(A, B, indexA + 1, indexB); + // 可能性2,丢掉B[indexB] + int p2 = B[indexB] + change(A, B, indexA, indexB + 1); + // 可能性3,同时丢掉A[indexA]、B[indexB] + // 可能性4,把A[indexA]改成B[indexB](也是B[indexB]改成A[indexA],因为代价一样) + // 可能性5,A[indexA]本来就是等于B[indexB]的,改的代价为0 + // 可以分析出可能性3,肯定是不如可能性4、可能性5的 + // 所以舍弃掉可能性3 + int p45 = Math.abs(A[indexA] - B[indexB]) + change(A, B, indexA + 1, indexB + 1); + return Math.min(Math.min(p1, p2), p45); + } + + // 上面的暴力递归方法改动态规划 + public static int change(int[] A, int[] B, int indexA, int indexB, int[][] dp) { + if (indexA == A.length && indexB == B.length) { + return 0; + } + if (dp[indexA][indexB] != -1) { + return dp[indexA][indexB]; + } + int ans = 0; + if (indexA == A.length && indexB != B.length) { + ans = B[indexB] + change(A, B, indexA, indexB + 1); + } else if (indexA != A.length && indexB == B.length) { + ans = A[indexA] + change(A, B, indexA + 1, indexB); + } else { + int p1 = A[indexA] + change(A, B, indexA + 1, indexB); + int p2 = B[indexB] + change(A, B, indexA, indexB + 1); + int p45 = Math.abs(A[indexA] - B[indexB]) + change(A, B, indexA + 1, indexB + 1); + ans = Math.min(Math.min(p1, p2), p45); + } + dp[indexA][indexB] = ans; + return ans; + } + +} diff --git a/算法周更班/class_2022_08_4_week/Code03_FindPosition.java b/算法周更班/class_2022_08_4_week/Code03_FindPosition.java new file mode 100644 index 0000000..2263080 --- /dev/null +++ b/算法周更班/class_2022_08_4_week/Code03_FindPosition.java @@ -0,0 +1,125 @@ +package class_2022_08_4_week; + +// 来自美团 +// 8.20笔试 +// 题目1 +// 小美将要期中考试,有n道题,对于第i道题, +// 小美有pi的几率做对,获得ai的分值,还有(1-pi)的概率做错,得0分。 +// 小美总分是每道题获得的分数。 +// 小美不甘于此,决定突击复习,因为时间有限,她最多复习m道题,复习后的试题正确率为100%。 +// 如果以最佳方式复习,能获得期望最大总分是多少? +// 输入n、m +// 接下来输入n个整数,代表pi%,为了简单期间,将概率扩大了100倍。 +// 接下来输入n个整数,代表ai,某道题的分值 +// 输出最大期望分值,精确到小数点后2位 +// 数据 1m<=n<=50000 +// 简单题, 课上提一下解法即可 +// 题目2 +// 小团在地图上放了3个定位装置,想依赖他们进行定位! +// 地图是一个n*n的棋盘, +// 有3个定位装置(x1,y1),(x2,y2),(x3,y3),每个值均在[1,n]内。 +// 小团在(a,b)位置放了一个信标, +// 每个定位装置会告诉小团它到信标的曼哈顿距离,也就是对于每个点,小团知道|xi-a|+|yi-b| +// 求信标位置,信标不唯一,输出字典序最小的。 +// 输入n,然后是3个定位装置坐标, +// 最后是3个定位装置到信标的曼哈顿记录。 +// 输出最小字典序的信标位置。 +// 1 <= 所有数据值 <= 50000 +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; + +public class Code03_FindPosition { + + public static int[] find(int n, + int[] a, int[] b, int[] c, + int ad, int bd, int cd) { + + int[] x1 = null; + int r1 = Integer.MAX_VALUE; + int[] x2 = null; + int r2 = 0; + int[] x3 = null; + int r3 = 0; + if (ad < r1) { + x1 = a; + r1 = ad; + x2 = b; + r2 = bd; + x3 = c; + r3 = cd; + } + if (bd < r1) { + x1 = b; + r1 = bd; + x2 = a; + r2 = ad; + x3 = c; + r3 = cd; + } + if (cd < r1) { + x1 = c; + r1 = cd; + x2 = a; + r2 = ad; + x3 = b; + r3 = bd; + } + // x1 r1 x2 r2 x3 r3 + int[] cur = { x1[0] - r1, x1[1] }; + Queue queue = new LinkedList<>(); + HashSet visited = new HashSet<>(); + ArrayList ans = new ArrayList<>(); + queue.add(cur); + visited.add(cur[0] + "_" + cur[1]); + + while (!queue.isEmpty()) { + // cur x1为圆心,r1为半径的圆周上 + cur = queue.poll(); + if ( + cur[0] >= 1 && cur[0] <= n + && + cur[1] >= 1 && cur[1] <= n + && + distance(cur[0], cur[1], x2) == r2 + && + distance(cur[0], cur[1], x3) == r3) { + ans.add(cur); + } + if (ans.size() == 2) { + break; + } + add(cur[0] - 1, cur[1] - 1, x1, r1, queue, visited); + add(cur[0] - 1, cur[1], x1, r1, queue, visited); + add(cur[0] - 1, cur[1] + 1, x1, r1, queue, visited); + add(cur[0], cur[1] - 1, x1, r1, queue, visited); + add(cur[0], cur[1] + 1, x1, r1, queue, visited); + add(cur[0] + 1, cur[1] - 1, x1, r1, queue, visited); + add(cur[0] + 1, cur[1], x1, r1, queue, visited); + add(cur[0] + 1, cur[1] + 1, x1, r1, queue, visited); + } + if (ans.size() == 1 + || ans.get(0)[0] < ans.get(1)[0] + || (ans.get(0)[0] == ans.get(1)[0] && ans.get(0)[1] < ans.get(1)[1])) { + return ans.get(0); + } else { + return ans.get(1); + } + } + + public static void add(int x, int y, + int[] c, int r, + Queue queue, HashSet visited) { + String key = x + "_" + y; + if (distance(x, y, c) == r && !visited.contains(key)) { + queue.add(new int[] { x, y }); + visited.add(key); + } + } + + public static int distance(int x, int y, int[] c) { + return Math.abs(x - c[0]) + Math.abs(y - c[1]); + } + +} diff --git a/算法周更班/class_2022_08_4_week/Code04_MaxPalindromeNumber.java b/算法周更班/class_2022_08_4_week/Code04_MaxPalindromeNumber.java new file mode 100644 index 0000000..e5f4a6e --- /dev/null +++ b/算法周更班/class_2022_08_4_week/Code04_MaxPalindromeNumber.java @@ -0,0 +1,93 @@ +package class_2022_08_4_week; + +// 来自微软 +// 给定一个字符串s,只含有0~9这些字符 +// 你可以使用来自s中的数字,目的是拼出一个最大的回文数 +// 使用数字的个数,不能超过s里含有的个数 +// 比如 : +// 39878,能拼出的最大回文数是 : 898 +// 00900,能拼出的最大回文数是 : 9 +// 54321,能拼出的最大回文数是 : 5 +// 最终的结果以字符串形式返回 +// str的长度为N,1 <= N <= 100000 +// 测试链接 : https://leetcode.cn/problems/largest-palindromic-number/ +import java.util.Comparator; +import java.util.HashMap; +import java.util.PriorityQueue; + +public class Code04_MaxPalindromeNumber { + + public static String largestPalindromic(String s) { + if (s == null || s.equals("")) { + return ""; + } + HashMap map = new HashMap<>(); + int n = s.length(); + for (int i = 0; i < n; i++) { + int number = s.charAt(i) - '0'; + map.put(number, map.getOrDefault(number, 0) + 1); + } + PriorityQueue heap = new PriorityQueue<>(new RecordComparator()); + for (int key : map.keySet()) { + heap.add(new Record(key, map.get(key))); + } + Record top = heap.poll(); + if (top.times == 1) { + return String.valueOf(top.number); + } else if (top.number == 0) { + return String.valueOf(heap.isEmpty() ? 0 : heap.peek().number); + } else { + StringBuilder left = new StringBuilder(); + left.append(top.number); + top.times -= 2; + if (top.times > 0) { + heap.add(top); + } + while (!heap.isEmpty() && heap.peek().times > 1) { + top = heap.poll(); + left.append(top.number); + top.times -= 2; + if (top.times > 0) { + heap.add(top); + } + } + StringBuilder ans = new StringBuilder(); + for (int i = 0; i < left.length(); i++) { + ans.append(left.charAt(i)); + } + if (!heap.isEmpty()) { + ans.append(heap.peek().number); + } + for (int i = left.length() - 1; i >= 0; i--) { + ans.append(left.charAt(i)); + } + return ans.toString(); + } + } + + public static class Record { + public int number; + public int times; + + public Record(int n, int t) { + number = n; + times = t; + } + } + + public static class RecordComparator implements Comparator { + + @Override + public int compare(Record o1, Record o2) { + if (o1.times == 1 && o2.times > 1) { + return 1; + } + if (o1.times > 1 && o2.times == 1) { + return -1; + } + return o2.number - o1.number; + } + + } + +} diff --git a/算法周更班/class_2022_08_4_week/Code05_TravelMinFuel.java b/算法周更班/class_2022_08_4_week/Code05_TravelMinFuel.java new file mode 100644 index 0000000..61dda18 --- /dev/null +++ b/算法周更班/class_2022_08_4_week/Code05_TravelMinFuel.java @@ -0,0 +1,85 @@ +package class_2022_08_4_week; + +// 来自微软 +// 给定两个数组A和B,比如 +// A = { 0, 1, 1 } +// B = { 1, 2, 3 } +// A[0] = 0, B[0] = 1,表示0到1有双向道路 +// A[1] = 1, B[1] = 2,表示1到2有双向道路 +// A[2] = 1, B[2] = 3,表示1到3有双向道路 +// 给定数字N,编号从0~N,所以一共N+1个节点 +// 题目输入一定保证所有节点都联通,并且一定没有环 +// 默认办公室是0节点,其他1~N节点上,每个节点上都有一个居民 +// 每天所有居民都去往0节点上班 +// 所有的居民都有一辆5座的车,也都乐意和别人一起坐车 +// 车不管负重是多少,只要走过一条路,就耗费1的汽油 +// 比如A、B、C的居民,开着自己的车来到D居民的位置,一共耗费3的汽油 +// D居民和E居民之间,假设有一条路 +// 那么D居民可以接上A、B、C,4个人可以用一辆车,去往E的话,就再耗费1的汽油 +// 求所有居民去办公室的路上,最少耗费多少汽油 +import java.util.ArrayList; + +public class Code05_TravelMinFuel { + + public static int cnt = 0; + + public static int minFuel(int[] a, int[] b, int n) { + // 先建图 + ArrayList> graph = new ArrayList<>(); + for (int i = 0; i <= n; i++) { + graph.add(new ArrayList<>()); + } + for (int i = 0; i < a.length; i++) { + graph.get(a[i]).add(b[i]); + graph.get(b[i]).add(a[i]); + } + // 建图完毕 + // 根据题目描述,办公室一定是0号点 + // 所有员工一定是往0号点汇聚 + + // a 号,dfn[a] == 0 没遍历过! + // dfn[a] != 0 遍历过! + int[] dfn = new int[n + 1]; + // a为头的树,一共有10个节点 + // size[a] = 0 + // size[a] = 10 + int[] size = new int[n + 1]; + // 所有居民要汇总吗? + // a为头的树,所有的居民是要向a来汇聚 + // cost[a] : 所有的居民要向a来汇聚,总油量的耗费 + int[] cost = new int[n + 1]; + cnt = 0; + dfs(graph, 0, dfn, size, cost); + return cost[0]; + } + + // 图 : graph + // 当前的头,原来的编号,不是dfn序号! : cur + // 从cur开始,请遍历 + // 遍历完成后,请把dfn[cur]填好!size[cur]填好!cost[cur]填好 + public static void dfs(ArrayList> graph, int cur, int[] dfn, int[] size, int[] cost) { + dfn[cur] = ++cnt; + size[cur] = 1; + for (int next : graph.get(cur)) { + if (dfn[next] == 0) { + dfs(graph, next, dfn, size, cost); + size[cur] += size[next]; + cost[cur] += cost[next]; + cost[cur] += (size[next] + 4) / 5; + } + } + } + + public static void main(String[] args) { + int[] a1 = { 0, 1, 1 }; + int[] b1 = { 1, 2, 3 }; + int n1 = 3; + System.out.println(minFuel(a1, b1, n1)); + + int[] a2 = { 1, 1, 1, 9, 9, 9, 9, 7, 8 }; + int[] b2 = { 2, 0, 3, 1, 6, 5, 4, 0, 0 }; + int n2 = 9; + System.out.println(minFuel(a2, b2, n2)); + } + +} diff --git a/算法周更班/class_2022_08_4_week/Code06_MinCostMostE.java b/算法周更班/class_2022_08_4_week/Code06_MinCostMostE.java new file mode 100644 index 0000000..91bdff0 --- /dev/null +++ b/算法周更班/class_2022_08_4_week/Code06_MinCostMostE.java @@ -0,0 +1,192 @@ +package class_2022_08_4_week; + +// 来自网易 +// 小红拿到了一个仅由r、e、d组成的字符串 +// 她定义一个字符e为"好e" : 当且仅当这个e字符和r、d相邻 +// 例如"reeder"只有一个"好e",前两个e都不是"好e",只有第三个e是"好e" +// 小红每次可以将任意字符修改为任意字符,即三种字符可以相互修改 +// 她希望"好e"的数量尽可能多 +// 小红想知道,自己最少要修改多少次 +// 输入一个只有r、e、d三种字符的字符串 +// 长度 <= 2 * 10^5 +// 输出最小修改次数 +public class Code06_MinCostMostE { + +// public static class Info { +// public int mostGoodE; +// public int minCost; +// +// public Info(int good, int cost) { +// mostGoodE = good; +// minCost = cost; +// } +// +// } +// +// // i-2 -> prepre +// // i-1 -> pre +// // i...可以去成全 i-1 pre +// // 也可以不成全 +// // i -> r e d 随意 +// // 返回:i-1 yes or no + i.... 最多的好e,数量是多少 +// // 最多的好e, 最小的代价 +// // i 2 * 10^5 +// // prepre r e d +// // pre r e d +// // 9 * 2 * 10^5 +// // 10^6 +// public static Info zuo(char[] s, int i, char prepre, char pre) { +// if (i == s.length) { +// return new Info(0, 0); +// } +// +// // 可能性1 i-1 [i] -> r +// int cur1Value = prepre == 'd' && pre == 'e' ? 1 : 0; +// int cur1Cost = s[i] == 'r' ? 0 : 1; +// Info info1 = zuo(s, i + 1, pre, 'r'); +// int p1Value = cur1Value + info1.mostGoodE; +// int p1Cost = cur1Cost + info1.minCost; +// +// // 可能性2 i-1 [i] -> e +// int cur2Value = 0; +// int cur2Cost = s[i] == 'e' ? 0 : 1; +// Info info2 = zuo(s, i + 1, pre, 'e'); +// int p2Value = cur2Value + info2.mostGoodE; +// int p2Cost = cur2Cost + info2.minCost; +// +// // 可能性3 i-1 [i] -> d +// int cur3Value = prepre == 'r' && pre == 'e' ? 1 : 0; +// int cur3Cost = s[i] == 'd' ? 0 : 1; +// Info info3 = zuo(s, i + 1, pre, 'd'); +// int p3Value = cur3Value + info3.mostGoodE; +// int p3Cost = cur3Cost + info3.minCost; +// +// int mostE = 0; +// int minCost = Integer.MAX_VALUE; +// +// if (mostE < p1Value) { +// mostE = p1Value; +// minCost = p1Cost; +// } else if (mostE == p1Value) { +// minCost = Math.min(minCost, p1Cost); +// } +// +// if (mostE < p2Value) { +// mostE = p2Value; +// minCost = p2Cost; +// } else if (mostE == p2Value) { +// minCost = Math.min(minCost, p2Cost); +// } +// +// if (mostE < p3Value) { +// mostE = p3Value; +// minCost = p3Cost; +// } else if (mostE == p3Value) { +// minCost = Math.min(minCost, p3Cost); +// } +// return new Info(mostE, minCost); +// } + + public static int minCost(String str) { + int n = str.length(); + if (n < 3) { + return -1; + } + int[] arr = new int[n]; + // d认为是0,e认为是1,r认为是2 + for (int i = 0; i < n; i++) { + char cur = str.charAt(i); + if (cur == 'd') { + arr[i] = 0; + } else if (cur == 'e') { + arr[i] = 1; + } else { + arr[i] = 2; + } + } + // 通过上面的转化,问题变成了: + // 1的左右,一定要被0和2包围,这个1才是"好1" + // 请让"好1"的尽量多,返回最少的修改代价 + int maxGood = 0; + int minCost = Integer.MAX_VALUE; + for (int prepre = 0; prepre < 3; prepre++) { + for (int pre = 0; pre < 3; pre++) { + int cost = arr[0] == prepre ? 0 : 1; + cost += arr[1] == pre ? 0 : 1; + Info cur = process(arr, 2, prepre, pre); + if (cur.maxGood > maxGood) { + maxGood = cur.maxGood; + minCost = cur.minCost + cost; + } else if (cur.maxGood == maxGood) { + minCost = Math.min(minCost, cur.minCost + cost); + } + } + } + return minCost; + } + + public static class Info { + public int maxGood; + public int minCost; + + public Info(int a, int b) { + maxGood = a; + minCost = b; + } + } + + // 暴力递归 + // 可以自己改成动态规划 + // arr[index-2]位置的数值是prepre + // arr[index-1]位置的数值是pre + // 在这种情况下,请让arr[index...]上的好1尽量多 + // 返回: + // 尽量多的"好1",是多少? + // 得到尽量多的"好1",最小代价是多少? + public static Info process(int[] arr, int index, int prepre, int pre) { + if (index == arr.length) { + return new Info(0, 0); + } + // 可能性1,arr[index],变成0 + int p1Value = prepre == 2 && pre == 1 ? 1 : 0; + int p1Cost = arr[index] == 0 ? 0 : 1; + Info info = process(arr, index + 1, pre, 0); + p1Value += info.maxGood; + p1Cost += info.minCost; + // 可能性2,arr[index],变成1 + int p2Value = 0; + int p2Cost = arr[index] == 1 ? 0 : 1; + info = process(arr, index + 1, pre, 1); + p2Value += info.maxGood; + p2Cost += info.minCost; + // 可能性3,arr[index],变成2 + int p3Value = prepre == 0 && pre == 1 ? 1 : 0; + int p3Cost = arr[index] == 2 ? 0 : 1; + info = process(arr, index + 1, pre, 2); + p3Value += info.maxGood; + p3Cost += info.minCost; + // 开始决策,选出三种可能性中的最优解 + int maxGood = 0; + int minCost = Integer.MAX_VALUE; + if (p1Value > maxGood) { + maxGood = p1Value; + minCost = p1Cost; + } else if (p1Value == maxGood) { + minCost = Math.min(minCost, p1Cost); + } + if (p2Value > maxGood) { + maxGood = p2Value; + minCost = p2Cost; + } else if (p2Value == maxGood) { + minCost = Math.min(minCost, p2Cost); + } + if (p3Value > maxGood) { + maxGood = p3Value; + minCost = p3Cost; + } else if (p3Value == maxGood) { + minCost = Math.min(minCost, p3Cost); + } + return new Info(maxGood, minCost); + } + +} diff --git a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) index 6a95a84..46a2266 100644 --- a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) +++ b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) @@ -1633,4 +1633,98 @@ https://leetcode.cn/problems/smallest-rotation-with-highest-score/ +第037节 2022年8月第4周流行算法题目解析 + +来自神策 +给定一个数组arr,表示连续n天的股价,数组下标表示第几天 +指标X:任意两天的股价之和 - 此两天间隔的天数 +比如 +第3天,价格是10 +第9天,价格是30 +那么第3天和第9天的指标X = 10 + 30 - (9 - 3) = 34 +返回arr中最大的指标X + +来自美团 +8.20笔试 +小团生日收到妈妈送的两个一模一样的数列作为礼物! +他很开心的把玩,不过不小心没拿稳将数列摔坏了! +现在他手上的两个数列分别为A和B,长度分别为n和m。 +小团很想再次让这两个数列变得一样。他现在能做两种操作: +操作一是将一个选定数列中的某一个数a改成数b,这会花费|b-a|的时间, +操作二是选择一个数列中某个数a,将它从数列中丢掉,花费|a|的时间。 +小团想知道,他最少能以多少时间将这两个数列变得再次相同! +输入描述: +第一行两个空格隔开的正整数n和m,分别表示数列A和B的长度。 +接下来一行n个整数,分别为A1 A2…An +接下来一行m个整数,分别为B1 B2…Bm +对于所有数据,1 ≤ n,m ≤ 2000, |Ai|,|Bi| ≤ 10000 +输出一行一个整数,表示最少花费时间,来使得两个数列相同。 + +来自美团 +题目1 +8.20笔试 +小美将要期中考试,有n道题,对于第i道题, +小美有pi的几率做对,获得ai的分值,还有(1-pi)的概率做错,得0分。 +小美总分是每道题获得的分数。 +小美不甘于此,决定突击复习,因为时间有限,她最多复习m道题,复习后的试题正确率为100%。 +如果以最佳方式复习,能获得期望最大总分是多少? +输入n、m +接下来输入n个整数,代表pi%,为了简单期间,将概率扩大了100倍。 +接下来输入n个整数,代表ai,某道题的分值 +输出最大期望分值,精确到小数点后2位 +数据 1m<=n<=50000 +简单题, 课上提一下解法即可 +题目2 +小团在地图上放了3个定位装置,想依赖他们进行定位! +地图是一个n*n的棋盘, +有3个定位装置(x1,y1),(x2,y2),(x3,y3),每个值均在[1,n]内。 +小团在(a,b)位置放了一个信标, +每个定位装置会告诉小团它到信标的曼哈顿距离,也就是对于每个点,小团知道|xi-a|+|yi-b| +求信标位置,信标不唯一,输出字典序最小的。 +输入n,然后是3个定位装置坐标, +最后是3个定位装置到信标的曼哈顿记录。 +输出最小字典序的信标位置。 +1 <= 所有数据值 <= 50000 + +来自微软 +给定一个字符串s,只含有0~9这些字符 +你可以使用来自s中的数字,目的是拼出一个最大的回文数 +使用数字的个数,不能超过s里含有的个数 +比如 : +39878,能拼出的最大回文数是 : 898 +00900,能拼出的最大回文数是 : 9 +54321,能拼出的最大回文数是 : 5 +最终的结果以字符串形式返回 +str的长度为N,1 <= N <= 100000 +测试链接 : https://leetcode.cn/problems/largest-palindromic-number/ + +来自微软 +给定两个数组A和B,比如 +A = { 0, 1, 1 } +B = { 1, 2, 3 } +A[0] = 0, B[0] = 1,表示0到1有双向道路 +A[1] = 1, B[1] = 2,表示1到2有双向道路 +A[2] = 1, B[2] = 3,表示1到3有双向道路 +给定数字N,编号从0~N,所以一共N+1个节点 +题目输入一定保证所有节点都联通,并且一定没有环 +默认办公室是0节点,其他1~N节点上,每个节点上都有一个居民 +每天所有居民都去往0节点上班 +所有的居民都有一辆5座的车,也都乐意和别人一起坐车 +车不管负重是多少,只要走过一条路,就耗费1的汽油 +比如A、B、C的居民,开着自己的车来到D居民的位置,一共耗费3的汽油 +D居民和E居民之间,假设有一条路 +那么D居民可以接上A、B、C,4个人可以用一辆车,去往E的话,就再耗费1的汽油 +求所有居民去办公室的路上,最少耗费多少汽油 + +来自网易 +小红拿到了一个仅由r、e、d组成的字符串 +她定义一个字符e为"好e" : 当且仅当这个e字符和r、d相邻 +例如"reeder"只有一个"好e",前两个e都不是"好e",只有第三个e是"好e" +小红每次可以将任意字符修改为任意字符,即三种字符可以相互修改 +她希望"好e"的数量尽可能多 +小红想知道,自己最少要修改多少次 +输入一个只有r、e、d三种字符的字符串 +长度 <= 2 * 10^5 +输出最小修改次数 +