diff --git a/算法周更班/class_2022_08_1_week/Code01_SidingPuzzle1.java b/算法周更班/class_2022_08_1_week/Code01_SidingPuzzle1.java new file mode 100644 index 0000000..dce8deb --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code01_SidingPuzzle1.java @@ -0,0 +1,136 @@ +package class_2022_08_1_week; + +import java.util.HashSet; +import java.util.PriorityQueue; + +// 在一个 2 * 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, +// 以及一块空缺用 0 来表示。一次 移动 定义为选择 0 与一个相邻的数字(上下左右)进行交换. +// 最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开。 +// 给出一个谜板的初始状态 board , +// 返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。 +// 测试链接 : https://leetcode.cn/problems/sliding-puzzle/ +public class Code01_SidingPuzzle1 { + + public static int b6 = 100000; + + public static int b5 = 10000; + + public static int b4 = 1000; + + public static int b3 = 100; + + public static int b2 = 10; + + public static int[] nexts = new int[3]; + + public static int[][] end = { { 1, 2 }, { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 0 }, { 1, 1 } }; + + // [1 0 2] + // [3 4 5] + // 102345 + public static int slidingPuzzle(int[][] m) { + HashSet set = new HashSet<>(); + int from = m[0][0] * b6 + m[0][1] * b5 + m[0][2] * b4 + m[1][0] * b3 + m[1][1] * b2 + m[1][2]; + PriorityQueue heap = new PriorityQueue<>((a, b) -> (a[0] + a[1]) - (b[0] + b[1])); + + // [ + // 从from出发到达当前状态,已经走了几步, + // 从当前状态到最终状态的估计距离 + // 当前状态是什么,用数字代表 + // ] + heap.add(new int[] { 0, distance(from), from }); + int ans = -1; + while (!heap.isEmpty()) { + int[] arr = heap.poll(); + int distance = arr[0]; + int cur = arr[2]; + if (set.contains(cur)) { + continue; + } + if (cur == 123450) { + ans = distance; + break; + } + set.add(cur); + int nextSize = nexts(cur); + for (int i = 0; i < nextSize; i++) { + int next = nexts[i]; + if (!set.contains(next)) { + heap.add(new int[] { distance + 1, distance(next), next }); + } + } + } + return ans; + } + + public static int nexts(int from) { + // 301245 + // 10000 + // a = 3 + int a = from / b6; + // b = 0 + int b = (from / b5) % 10; + // c = 1 + int c = (from / b4) % 10; + // d = 2 + int d = (from / b3) % 10; + // e = 4 + int e = (from / b2) % 10; + // f = 5 + int f = from % 10; + if (a == 0) { + nexts[0] = from + (b - a) * b6 + (a - b) * b5; + nexts[1] = from + (d - a) * b6 + (a - d) * b3; + return 2; + } else if (b == 0) { + nexts[0] = from + (a - b) * b5 + (b - a) * b6; + nexts[1] = from + (c - b) * b5 + (b - c) * b4; + nexts[2] = from + (e - b) * b5 + (b - e) * b2; + return 3; + } else if (c == 0) { + nexts[0] = from + (b - c) * b4 + (c - b) * b5; + nexts[1] = from + (f - c) * b4 + (c - f); + return 2; + } else if (d == 0) { + nexts[0] = from + (a - d) * b3 + (d - a) * b6; + nexts[1] = from + (e - d) * b3 + (d - e) * b2; + return 2; + } else if (e == 0) { + nexts[0] = from + (b - e) * b2 + (e - b) * b5; + nexts[1] = from + (d - e) * b2 + (e - d) * b3; + nexts[2] = from + (f - e) * b2 + (e - f); + return 3; + } else { + nexts[0] = from + (e - f) + (f - e) * b2; + nexts[1] = from + (c - f) + (f - c) * b4; + return 2; + } + } + + // 当前的数,num + // 最终要去的数,123450 + // 返回num -> 123450 曼哈顿距离! + public static int distance(int num) { + int ans = end[num / b6][0] + end[num / b6][1]; + ans += end[(num / b5) % 10][0] + Math.abs(end[(num / b5) % 10][1] - 1); + ans += end[(num / b4) % 10][0] + Math.abs(end[(num / b4) % 10][1] - 2); + ans += Math.abs(end[(num / b3) % 10][0] - 1) + end[(num / b3) % 10][1]; + ans += Math.abs(end[(num / b2) % 10][0] - 1) + Math.abs(end[(num / b2) % 10][1] - 1); + ans += Math.abs(end[num % 10][0] - 1) + Math.abs(end[num % 10][1] - 2); + return ans; + } + + + public static void main(String[] args) { + int from = 301245; + int size = nexts(from); + for(int i = 0 ;i < size;i++) { + System.out.println(nexts[i]); + } + int num = 314502; + System.out.println(distance(num)); + } + + + +} diff --git a/算法周更班/class_2022_08_1_week/Code01_SidingPuzzle2.java b/算法周更班/class_2022_08_1_week/Code01_SidingPuzzle2.java new file mode 100644 index 0000000..12d7edd --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code01_SidingPuzzle2.java @@ -0,0 +1,120 @@ +package class_2022_08_1_week; + +// 在一个 2 * 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, +// 以及一块空缺用 0 来表示。一次 移动 定义为选择 0 与一个相邻的数字(上下左右)进行交换. +// 最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开。 +// 给出一个谜板的初始状态 board , +// 返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。 +// 测试链接 : https://leetcode.cn/problems/sliding-puzzle/ +public class Code01_SidingPuzzle2 { + + public static int[] status = { 12345, 12354, 12435, 12453, 12534, 12543, 13245, 13254, 13425, 13452, 13524, 13542, + 14235, 14253, 14325, 14352, 14523, 14532, 15234, 15243, 15324, 15342, 15423, 15432, 21345, 21354, 21435, + 21453, 21534, 21543, 23145, 23154, 23415, 23451, 23514, 23541, 24135, 24153, 24315, 24351, 24513, 24531, + 25134, 25143, 25314, 25341, 25413, 25431, 31245, 31254, 31425, 31452, 31524, 31542, 32145, 32154, 32415, + 32451, 32514, 32541, 34125, 34152, 34215, 34251, 34512, 34521, 35124, 35142, 35214, 35241, 35412, 35421, + 41235, 41253, 41325, 41352, 41523, 41532, 42135, 42153, 42315, 42351, 42513, 42531, 43125, 43152, 43215, + 43251, 43512, 43521, 45123, 45132, 45213, 45231, 45312, 45321, 51234, 51243, 51324, 51342, 51423, 51432, + 52134, 52143, 52314, 52341, 52413, 52431, 53124, 53142, 53214, 53241, 53412, 53421, 54123, 54132, 54213, + 54231, 54312, 54321, 102345, 102354, 102435, 102453, 102534, 102543, 103245, 103254, 103425, 103452, 103524, + 103542, 104235, 104253, 104325, 104352, 104523, 104532, 105234, 105243, 105324, 105342, 105423, 105432, + 120345, 120354, 120435, 120453, 120534, 120543, 123045, 123054, 123405, 123450, 123504, 123540, 124035, + 124053, 124305, 124350, 124503, 124530, 125034, 125043, 125304, 125340, 125403, 125430, 130245, 130254, + 130425, 130452, 130524, 130542, 132045, 132054, 132405, 132450, 132504, 132540, 134025, 134052, 134205, + 134250, 134502, 134520, 135024, 135042, 135204, 135240, 135402, 135420, 140235, 140253, 140325, 140352, + 140523, 140532, 142035, 142053, 142305, 142350, 142503, 142530, 143025, 143052, 143205, 143250, 143502, + 143520, 145023, 145032, 145203, 145230, 145302, 145320, 150234, 150243, 150324, 150342, 150423, 150432, + 152034, 152043, 152304, 152340, 152403, 152430, 153024, 153042, 153204, 153240, 153402, 153420, 154023, + 154032, 154203, 154230, 154302, 154320, 201345, 201354, 201435, 201453, 201534, 201543, 203145, 203154, + 203415, 203451, 203514, 203541, 204135, 204153, 204315, 204351, 204513, 204531, 205134, 205143, 205314, + 205341, 205413, 205431, 210345, 210354, 210435, 210453, 210534, 210543, 213045, 213054, 213405, 213450, + 213504, 213540, 214035, 214053, 214305, 214350, 214503, 214530, 215034, 215043, 215304, 215340, 215403, + 215430, 230145, 230154, 230415, 230451, 230514, 230541, 231045, 231054, 231405, 231450, 231504, 231540, + 234015, 234051, 234105, 234150, 234501, 234510, 235014, 235041, 235104, 235140, 235401, 235410, 240135, + 240153, 240315, 240351, 240513, 240531, 241035, 241053, 241305, 241350, 241503, 241530, 243015, 243051, + 243105, 243150, 243501, 243510, 245013, 245031, 245103, 245130, 245301, 245310, 250134, 250143, 250314, + 250341, 250413, 250431, 251034, 251043, 251304, 251340, 251403, 251430, 253014, 253041, 253104, 253140, + 253401, 253410, 254013, 254031, 254103, 254130, 254301, 254310, 301245, 301254, 301425, 301452, 301524, + 301542, 302145, 302154, 302415, 302451, 302514, 302541, 304125, 304152, 304215, 304251, 304512, 304521, + 305124, 305142, 305214, 305241, 305412, 305421, 310245, 310254, 310425, 310452, 310524, 310542, 312045, + 312054, 312405, 312450, 312504, 312540, 314025, 314052, 314205, 314250, 314502, 314520, 315024, 315042, + 315204, 315240, 315402, 315420, 320145, 320154, 320415, 320451, 320514, 320541, 321045, 321054, 321405, + 321450, 321504, 321540, 324015, 324051, 324105, 324150, 324501, 324510, 325014, 325041, 325104, 325140, + 325401, 325410, 340125, 340152, 340215, 340251, 340512, 340521, 341025, 341052, 341205, 341250, 341502, + 341520, 342015, 342051, 342105, 342150, 342501, 342510, 345012, 345021, 345102, 345120, 345201, 345210, + 350124, 350142, 350214, 350241, 350412, 350421, 351024, 351042, 351204, 351240, 351402, 351420, 352014, + 352041, 352104, 352140, 352401, 352410, 354012, 354021, 354102, 354120, 354201, 354210, 401235, 401253, + 401325, 401352, 401523, 401532, 402135, 402153, 402315, 402351, 402513, 402531, 403125, 403152, 403215, + 403251, 403512, 403521, 405123, 405132, 405213, 405231, 405312, 405321, 410235, 410253, 410325, 410352, + 410523, 410532, 412035, 412053, 412305, 412350, 412503, 412530, 413025, 413052, 413205, 413250, 413502, + 413520, 415023, 415032, 415203, 415230, 415302, 415320, 420135, 420153, 420315, 420351, 420513, 420531, + 421035, 421053, 421305, 421350, 421503, 421530, 423015, 423051, 423105, 423150, 423501, 423510, 425013, + 425031, 425103, 425130, 425301, 425310, 430125, 430152, 430215, 430251, 430512, 430521, 431025, 431052, + 431205, 431250, 431502, 431520, 432015, 432051, 432105, 432150, 432501, 432510, 435012, 435021, 435102, + 435120, 435201, 435210, 450123, 450132, 450213, 450231, 450312, 450321, 451023, 451032, 451203, 451230, + 451302, 451320, 452013, 452031, 452103, 452130, 452301, 452310, 453012, 453021, 453102, 453120, 453201, + 453210, 501234, 501243, 501324, 501342, 501423, 501432, 502134, 502143, 502314, 502341, 502413, 502431, + 503124, 503142, 503214, 503241, 503412, 503421, 504123, 504132, 504213, 504231, 504312, 504321, 510234, + 510243, 510324, 510342, 510423, 510432, 512034, 512043, 512304, 512340, 512403, 512430, 513024, 513042, + 513204, 513240, 513402, 513420, 514023, 514032, 514203, 514230, 514302, 514320, 520134, 520143, 520314, + 520341, 520413, 520431, 521034, 521043, 521304, 521340, 521403, 521430, 523014, 523041, 523104, 523140, + 523401, 523410, 524013, 524031, 524103, 524130, 524301, 524310, 530124, 530142, 530214, 530241, 530412, + 530421, 531024, 531042, 531204, 531240, 531402, 531420, 532014, 532041, 532104, 532140, 532401, 532410, + 534012, 534021, 534102, 534120, 534201, 534210, 540123, 540132, 540213, 540231, 540312, 540321, 541023, + 541032, 541203, 541230, 541302, 541320, 542013, 542031, 542103, 542130, 542301, 542310, 543012, 543021, + 543102, 543120, 543201, 543210 }; + + public static int[] ans = { 15, -1, -1, 3, 15, -1, -1, 15, 3, -1, -1, 17, 17, -1, -1, 15, 13, -1, -1, 17, 13, -1, + -1, 7, -1, 21, 15, -1, -1, 13, 3, -1, -1, 11, 11, -1, -1, 9, 15, -1, -1, 15, 9, -1, -1, 15, 17, -1, 15, -1, + -1, 11, 19, -1, -1, 13, 17, -1, -1, 19, 13, -1, -1, 15, 13, -1, -1, 7, 9, -1, -1, 11, -1, 9, 13, -1, -1, 9, + 17, -1, -1, 15, 7, -1, -1, 17, 7, -1, -1, 11, 19, -1, -1, 11, 11, -1, 17, -1, -1, 13, 11, -1, -1, 5, 13, -1, + -1, 15, 11, -1, -1, 15, 17, -1, -1, 11, 11, -1, -1, 15, 14, -1, -1, 2, 14, -1, -1, 14, 2, -1, -1, 16, 16, + -1, -1, 14, 12, -1, -1, 16, 12, -1, -1, 6, 13, -1, -1, 1, 13, -1, 2, -1, 1, 0, -1, -1, -1, 10, -1, -1, 11, + 12, 10, -1, 11, 12, -1, -1, -1, 15, 3, -1, -1, 17, -1, 14, -1, -1, 15, 16, 14, -1, 15, 16, -1, -1, -1, 6, + -1, -1, 5, 4, 17, -1, -1, 15, 13, -1, 16, -1, 15, 16, -1, -1, -1, 16, -1, -1, 15, 14, 18, -1, 17, 18, -1, + -1, -1, 15, 13, -1, -1, 5, -1, 4, -1, -1, 3, 4, 12, -1, 13, 14, -1, -1, -1, 12, -1, -1, 13, 14, -1, 20, 16, + -1, -1, 12, 4, -1, -1, 12, 12, -1, -1, 8, 16, -1, -1, 14, 8, -1, -1, 16, 16, -1, -1, 19, 17, -1, -1, 13, -1, + 14, -1, -1, 13, 14, 18, -1, 17, 18, -1, -1, -1, 18, -1, -1, 17, 18, 5, -1, -1, 13, 13, -1, 16, -1, 15, 14, + -1, -1, -1, 16, -1, -1, 15, 14, 8, -1, 7, 6, -1, -1, -1, 7, 15, -1, -1, 13, -1, 10, -1, -1, 11, 12, 6, -1, + 5, 6, -1, -1, -1, 12, -1, -1, 13, 14, 9, -1, -1, 15, 15, -1, 18, -1, 19, 16, -1, -1, -1, 14, -1, -1, 13, 14, + 10, -1, 9, 10, -1, -1, 14, -1, -1, 12, 18, -1, -1, 12, 16, -1, -1, 18, 12, -1, -1, 14, 14, -1, -1, 8, 10, + -1, -1, 12, 13, -1, -1, 13, 17, -1, 16, -1, 15, 14, -1, -1, -1, 16, -1, -1, 15, 16, 12, -1, 11, 12, -1, -1, + -1, 13, 15, -1, -1, 19, -1, 20, -1, -1, 19, 20, 14, -1, 13, 14, -1, -1, -1, 14, -1, -1, 13, 14, 11, -1, -1, + 15, 15, -1, 14, -1, 15, 16, -1, -1, -1, 16, -1, -1, 17, 16, 10, -1, 9, 10, -1, -1, -1, 9, 11, -1, -1, 13, + -1, 14, -1, -1, 13, 14, 12, -1, 11, 10, -1, -1, -1, 14, -1, -1, 13, 12, -1, 8, 12, -1, -1, 8, 18, -1, -1, + 14, 6, -1, -1, 18, 6, -1, -1, 10, 20, -1, -1, 10, 10, -1, -1, 7, 11, -1, -1, 7, -1, 4, -1, -1, 5, 6, 4, -1, + 5, 6, -1, -1, -1, 8, -1, -1, 9, 10, 19, -1, -1, 15, 7, -1, 14, -1, 13, 14, -1, -1, -1, 10, -1, -1, 9, 8, 18, + -1, 19, 20, -1, -1, -1, 19, 7, -1, -1, 11, -1, 10, -1, -1, 9, 10, 18, -1, 19, 20, -1, -1, -1, 10, -1, -1, 9, + 8, 21, -1, -1, 11, 11, -1, 10, -1, 9, 10, -1, -1, -1, 14, -1, -1, 13, 12, 18, -1, 19, 20, -1, -1, 16, -1, + -1, 12, 12, -1, -1, 6, 14, -1, -1, 16, 10, -1, -1, 14, 16, -1, -1, 10, 12, -1, -1, 14, 15, -1, -1, 13, 13, + -1, 16, -1, 15, 14, -1, -1, -1, 16, -1, -1, 15, 14, 14, -1, 13, 14, -1, -1, -1, 7, 15, -1, -1, 15, -1, 14, + -1, -1, 13, 14, 10, -1, 9, 8, -1, -1, -1, 16, -1, -1, 15, 16, 11, -1, -1, 15, 17, -1, 18, -1, 17, 18, -1, + -1, -1, 18, -1, -1, 17, 18, 12, -1, 11, 12, -1, -1, -1, 9, 13, -1, -1, 13, -1, 10, -1, -1, 11, 12, 8, -1, 7, + 8, -1, -1, -1, 12, -1, -1, 13, 14 }; + + public static int slidingPuzzle(int[][] board) { + int from = board[0][0] * 100000 + board[0][1] * 10000 + board[0][2] * 1000 + board[1][0] * 100 + + board[1][1] * 10 + board[1][2]; + return ans[find(from)]; + } + + public static int find(int num) { + int ans = 0; + int l = 0; + int r = status.length - 1; + int m = 0; + while (l <= r) { + m = (l + r) / 2; + if (status[m] == num) { + ans = m; + break; + } else if (status[m] > num) { + r = m - 1; + } else { + l = m + 1; + } + } + return ans; + } + +} diff --git a/算法周更班/class_2022_08_1_week/Code02_WaterKing.java b/算法周更班/class_2022_08_1_week/Code02_WaterKing.java new file mode 100644 index 0000000..b492270 --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code02_WaterKing.java @@ -0,0 +1,34 @@ +package class_2022_08_1_week; + +// 找到数组中的水王数 +// 本题来自,大厂刷题班,23节 +// 为了讲述下一个题,才重新讲述这个题 +// 比较简单 +public class Code02_WaterKing { + + public static int waterKing(int[] arr) { + int cand = 0; + int hp = 0; + for (int i = 0; i < arr.length; i++) { + if (hp == 0) { + cand = arr[i]; + hp = 1; + } else if (arr[i] == cand) { + hp++; + } else { + hp--; + } + } + if (hp == 0) { + return -1; + } + hp = 0; + for (int i = 0; i < arr.length; i++) { + if (arr[i] == cand) { + hp++; + } + } + return hp > arr.length / 2 ? cand : -1; + } + +} diff --git a/算法周更班/class_2022_08_1_week/Code03_OnlineMajorityElementInSubarray.java b/算法周更班/class_2022_08_1_week/Code03_OnlineMajorityElementInSubarray.java new file mode 100644 index 0000000..f76c037 --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code03_OnlineMajorityElementInSubarray.java @@ -0,0 +1,145 @@ +package class_2022_08_1_week; + +import java.util.ArrayList; + +// 设计一个数据结构,有效地找到给定子数组的 多数元素 。 +// 子数组的 多数元素 是在子数组中出现 threshold 次数或次数以上的元素。 +// 实现 MajorityChecker 类: +// MajorityChecker(int[] arr)  +// 会用给定的数组 arr 对 MajorityChecker 初始化。 +// int query(int left, int right, int threshold)  +// 返回子数组中的元素  arr[left...right] 至少出现 threshold 次数, +// 如果不存在这样的元素则返回 -1。 +// 为了让同学们听懂这个题 +// 才安排的水王问题重讲 +// 测试链接 : https://leetcode.cn/problems/online-majority-element-in-subarray/ +public class Code03_OnlineMajorityElementInSubarray { + + class MajorityChecker { + + SegmentTree st; + + CountQuicker cq; + + public MajorityChecker(int[] arr) { + st = new SegmentTree(arr); + cq = new CountQuicker(arr); + } + + public int query(int left, int right, int threshold) { + int candidate = st.query(left, right); + return cq.realTimes(left, right, candidate) >= threshold ? candidate : -1; + } + + class SegmentTree { + int n; + int[] candidate; + int[] hp; + + public SegmentTree(int[] arr) { + n = arr.length; + candidate = new int[(n + 1) << 2]; + hp = new int[(n + 1) << 2]; + build(arr, 1, n, 1); + } + + private void build(int[] arr, int l, int r, int rt) { + if (l == r) { + candidate[rt] = arr[l - 1]; + hp[rt] = 1; + } else { + int m = (l + r) >> 1; + build(arr, l, m, rt << 1); + build(arr, m + 1, r, rt << 1 | 1); + int lc = candidate[rt << 1]; + int rc = candidate[rt << 1 | 1]; + int lh = hp[rt << 1]; + int rh = hp[rt << 1 | 1]; + if (lc == rc) { + candidate[rt] = lc; + hp[rt] = lh + rh; + } else { + candidate[rt] = lh >= rh ? lc : rc; + hp[rt] = Math.abs(lh - rh); + } + } + } + + public int query(int left, int right) { + return query(left + 1, right + 1, 1, n, 1)[0]; + } + + private int[] query(int L, int R, int l, int r, int rt) { + if (L <= l && r <= R) { + return new int[] { candidate[rt], hp[rt] }; + } + int m = (l + r) >> 1; + if (R <= m) { + return query(L, R, l, m, rt << 1); + } else if (L > m) { + return query(L, R, m + 1, r, rt << 1 | 1); + } else { + int[] ansl = query(L, R, l, m, rt << 1); + int[] ansr = query(L, R, m + 1, r, rt << 1 | 1); + if (ansl[0] == ansr[0]) { + ansl[1] += ansr[1]; + return ansl; + } else { + if (ansl[1] >= ansr[1]) { + ansl[1] -= ansr[1]; + return ansl; + } else { + ansr[1] -= ansl[1]; + return ansr; + } + } + } + } + + } + + class CountQuicker { + + // v : i1 i14 i15 + ArrayList> cnt; + + public CountQuicker(int[] arr) { + cnt = new ArrayList<>(); + int max = 0; + for (int num : arr) { + max = Math.max(max, num); + } + for (int i = 0; i <= max; i++) { + cnt.add(new ArrayList<>()); + } + for (int i = 0; i < arr.length; i++) { + cnt.get(arr[i]).add(i); + } + } + + public int realTimes(int left, int right, int num) { + ArrayList indies = cnt.get(num); + return size(indies, right) - size(indies, left - 1); + } + + private int size(ArrayList indies, int index) { + int l = 0; + int r = indies.size() - 1; + int m = 0; + int ans = -1; + while (l <= r) { + m = (l + r) / 2; + if (indies.get(m) <= index) { + ans = m; + l = m + 1; + } else { + r = m - 1; + } + } + return ans + 1; + } + } + + } + +} diff --git a/算法周更班/class_2022_08_1_week/Code04_ShortestImpossibleSequenceOfRolls.java b/算法周更班/class_2022_08_1_week/Code04_ShortestImpossibleSequenceOfRolls.java new file mode 100644 index 0000000..64b669f --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code04_ShortestImpossibleSequenceOfRolls.java @@ -0,0 +1,37 @@ +package class_2022_08_1_week; + +import java.util.Arrays; + +// 给你一个长度为 n 的整数数组 rolls 和一个整数 k 。 +// 你扔一个 k 面的骰子 n 次,骰子的每个面分别是 1 到 k , +// 其中第 i 次扔得到的数字是 rolls[i] 。 +// 请你返回 无法 从 rolls 中得到的 最短 骰子子序列的长度。 +// 扔一个 k 面的骰子 len 次得到的是一个长度为 len 的 骰子子序列 。 +// 注意 ,子序列只需要保持在原数组中的顺序,不需要连续。 +// 测试链接 : https://leetcode.cn/problems/shortest-impossible-sequence-of-rolls/ +public class Code04_ShortestImpossibleSequenceOfRolls { + + // 所有数字1~k + public static int shortestSequence(int[] rolls, int k) { + // 1~k上,某个数字是否收集到了! + // set[i] == true + // set[i] == false + boolean[] set = new boolean[k + 1]; + // 当前这一套,收集了几个数字了? + int size = 0; + int ans = 0; + for (int num : rolls) { + if (!set[num]) { + set[num] = true; + size++; + } + if (size == k) { + ans++; + Arrays.fill(set, false); + size = 0; + } + } + return ans + 1; + } + +} diff --git a/算法周更班/class_2022_08_1_week/Code05_LongestOneLetterManyNumberString.java b/算法周更班/class_2022_08_1_week/Code05_LongestOneLetterManyNumberString.java new file mode 100644 index 0000000..9644000 --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code05_LongestOneLetterManyNumberString.java @@ -0,0 +1,103 @@ +package class_2022_08_1_week; + +// 给定一个只由小写字母和数字字符组成的字符串str +// 要求子串必须只含有一个小写字母,数字字符数量随意 +// 求这样的子串最大长度是多少 +public class Code05_LongestOneLetterManyNumberString { + + // 一个绝对正确的暴力方法 + public static int right(String s) { + char[] str = s.toCharArray(); + int ans = 0; + for (int i = 0; i < str.length; i++) { + for (int j = i; j < str.length; j++) { + if (check(str, i, j)) { + ans = Math.max(ans, j - i + 1); + } + } + } + return ans; + } + + public static boolean check(char[] str, int l, int r) { + int letterNumber = 0; + for (int i = l; i <= r; i++) { + if (str[i] >= 'a' && str[i] <= 'z') { + letterNumber++; + } + } + return letterNumber == 1; + } + + // 用窗口 + // 时间复杂度O(N) + public static int zuo(String s) { + char[] str = s.toCharArray(); + int n = str.length; + // 窗口内有几个小写字母了 + int letters = 0; + // 窗口的右边界 + // [left, right) + int right = 0; + int ans = 0; + // for枚举了每一个窗口的开始位置,0... 1...... 2..... + for (int left = 0; left < n; left++) { + while (right < n) { // right不能越界,一旦越界不用再往右了 + if (letters == 1 && str[right] >= 'a' && str[right] <= 'z') { + break; + } + // letters == 0 str[right]是数字 + if (str[right] >= 'a' && str[right] <= 'z') { + letters++; + } + right++; + } + // [left.....right) + // [left.....right-1] + if (letters == 1) { + ans = Math.max(ans, right - left); + } + if (str[left] >= 'a' && str[left] <= 'z') { + letters--; + } + } + return ans; + } + + // 为了测试 + public static char[] chars = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z' }; + + // 为了测试 + public static String randomString(int n) { + char[] str = new char[n]; + for (int i = 0; i < n; i++) { + str[i] = chars[(int) (Math.random() * chars.length)]; + } + return String.valueOf(str); + } + + // 为了测试 + public static void main(String[] args) { + int N = 100; + int testTimes = 10000; + System.out.println("测试开始"); + for (int i = 0; i < testTimes; i++) { + int n = (int) (Math.random() * N) + 1; + String str = randomString(n); + int ans1 = right(str); + int ans2 = zuo(str); + if (ans1 != ans2) { + System.out.println(str); + System.out.println(ans1); + System.out.println(ans2); + break; + } + } + System.out.println("测试结束"); + } + +} diff --git a/算法周更班/class_2022_08_1_week/Code06_SortStackUsingRecursive.java b/算法周更班/class_2022_08_1_week/Code06_SortStackUsingRecursive.java new file mode 100644 index 0000000..06f2abf --- /dev/null +++ b/算法周更班/class_2022_08_1_week/Code06_SortStackUsingRecursive.java @@ -0,0 +1,138 @@ +package class_2022_08_1_week; + +import java.util.Stack; + +// 栈只提供push、pop、isEmpty三个方法 +// 请完成无序栈的排序,要求排完序之后,从栈顶到栈底从小到大 +// 只能使用栈提供的push、pop、isEmpty三个方法、以及递归函数 +// 除此之外不能使用任何的容器,任何容器都不许,连数组也不行 +// 也不能自己定义任何结构体 +// 就是只用: +// 1) 栈提供的push、pop、isEmpty三个方法 +// 2) 简单返回值的递归函数 +public class Code06_SortStackUsingRecursive { + + public static void sortStack(Stack stack) { + int deep = deep(stack); + while (deep > 0) { + int max = max(stack, deep); + int k = times(stack, max, deep); + down(stack, deep, max, k); + deep -= k; + } + } + + // 返回栈的深度 + // 不改变栈的数据状况 + // stack push pop isEmpty + public static int deep(Stack stack) { + if (stack.isEmpty()) { + return 0; + } + int num = stack.pop(); + int deep = deep(stack) + 1; + stack.push(num); + return deep; + } + + // 从栈当前的顶部开始,往下数deep层 + // ) 返回这deep层里的最大值 + public static int max(Stack stack, int deep) { + if (deep == 0) { + return Integer.MIN_VALUE; + } + int num = stack.pop(); + int restMax = max(stack, deep - 1); + int max = Math.max(num, restMax); + stack.push(num); + return max; + } + + // 从栈当前的顶部开始,往下数deep层,已知最大值是max了 + // 返回,max出现了几次,不改变栈的数据状况 + public static int times(Stack stack, int max, int deep) { + if (deep == 0) { + return 0; + } + int num = stack.pop(); + int restTimes = times(stack, max, deep - 1); + int times = restTimes + (num == max ? 1 : 0); + stack.push(num); + return times; + } + + // 从栈当前的顶部开始,往下数deep层,已知最大值是max,出现了k次 + // 请把这k个最大值沉底,剩下的数据状况不变 + public static void down(Stack stack, int deep, int max, int k) { + if (deep == 0) { + for (int i = 0; i < k; i++) { + stack.push(max); + } + } else { + int num = stack.pop(); + down(stack, deep - 1, max, k); + if (num != max) { + stack.push(num); + } + } + } + + // 为了测试 + // 生成随机栈 + public static Stack generateRandomStack(int n, int v) { + Stack ans = new Stack(); + for (int i = 0; i < n; i++) { + ans.add((int) (Math.random() * v)); + } + return ans; + } + + // 为了测试 + // 检测栈是不是有序的 + public static boolean isSorted(Stack stack) { + int step = Integer.MIN_VALUE; + while (!stack.isEmpty()) { + if (step > stack.peek()) { + return false; + } + step = stack.pop(); + } + return true; + } + + // 为了测试 + public static void main(String[] args) { + Stack test = new Stack(); + test.add(1); + test.add(5); + test.add(4); + test.add(5); + test.add(3); + test.add(2); + test.add(3); + test.add(1); + test.add(4); + test.add(2); + // 1 5 4 5 3 2 3 1 4 2 + sortStack(test); + while (!test.isEmpty()) { + System.out.println(test.pop()); + } + + int N = 20; + int V = 20; + int testTimes = 20000; + System.out.println("测试开始"); + for (int i = 0; i < testTimes; i++) { + int n = (int) (Math.random() * N); + Stack stack = generateRandomStack(n, V); + sortStack(stack); + if (!isSorted(stack)) { + System.out.println("出错了!"); + break; + } + } + System.out.println("测试结束"); + } + +} diff --git a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) index a668863..ac634bc 100644 --- a/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) +++ b/算法课堂笔记/课堂内容汇总/每周有营养的大厂算法面试题(正在直播) @@ -1486,3 +1486,57 @@ nums 中的 子集 是通过删除 nums 中一些(可能一个都不删除 测试链接 : https://leetcode.cn/problems/the-number-of-good-subsets/ + +第034节 2022年8月第1周流行算法题目解析 + +在一个 2 * 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, +以及一块空缺用 0 来表示。一次 移动 定义为选择 0 与一个相邻的数字(上下左右)进行交换. +最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开。 +给出一个谜板的初始状态 board , +返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。 +测试链接 : https://leetcode.cn/problems/sliding-puzzle/ + +找到数组中的水王数 +本题来自,大厂刷题班,23节 +为了讲述下一个题,才重新讲述这个题 +比较简单 + +设计一个数据结构,有效地找到给定子数组的 多数元素 。 +子数组的 多数元素 是在子数组中出现 threshold 次数或次数以上的元素。 +实现 MajorityChecker 类: +MajorityChecker(int[] arr)  +会用给定的数组 arr 对 MajorityChecker 初始化。 +int query(int left, int right, int threshold)  +返回子数组中的元素  arr[left...right] 至少出现 threshold 次数, +如果不存在这样的元素则返回 -1。 +为了让同学们听懂这个题 +才安排的水王问题重讲 +测试链接 : https://leetcode.cn/problems/online-majority-element-in-subarray/ + +给你一个长度为 n 的整数数组 rolls 和一个整数 k 。 +你扔一个 k 面的骰子 n 次,骰子的每个面分别是 1 到 k , +其中第 i 次扔得到的数字是 rolls[i] 。 +请你返回 无法 从 rolls 中得到的 最短 骰子子序列的长度。 +扔一个 k 面的骰子 len 次得到的是一个长度为 len 的 骰子子序列 。 +注意 ,子序列只需要保持在原数组中的顺序,不需要连续。 +测试链接 : https://leetcode.cn/problems/shortest-impossible-sequence-of-rolls/ + +给定一个只由小写字母和数字字符组成的字符串str +要求子串必须只含有一个小写字母,数字字符数量随意 +求这样的子串最大长度是多少 + +栈只提供push、pop、isEmpty三个方法 +请完成无序栈的排序,要求排完序之后,从栈顶到栈底从小到大 +只能使用栈提供的push、pop、isEmpty三个方法、以及递归函数 +除此之外不能使用任何的容器,任何容器都不许,连数组也不行 +也不能自己定义任何结构体 +就是只用: +1) 栈提供的push、pop、isEmpty三个方法 +2) 简单返回值的递归函数 + + + + + + +