From 68af47bb889c1fa695249fc3ea0542aee77d324d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B7=A6=E7=A8=8B=E4=BA=91?= Date: Thu, 31 Dec 2020 19:20:45 +0800 Subject: [PATCH] modify code --- src/class18/Code01_RobotWalk.java | 35 ++-- ...e03_Knapsack.java => Code02_Knapsack.java} | 8 +- src/class18/Code02_StickersToSpellWord.java | 152 ------------------ ...rdsInLine.java => Code03_CardsInLine.java} | 2 +- ...java => Code04_ConvertToLetterString.java} | 2 +- src/class18/Code05_StickersToSpellWord.java | 140 ++++++++++++++++ 6 files changed, 156 insertions(+), 183 deletions(-) rename src/class18/{Code03_Knapsack.java => Code02_Knapsack.java} (93%) delete mode 100644 src/class18/Code02_StickersToSpellWord.java rename src/class18/{Code04_CardsInLine.java => Code03_CardsInLine.java} (97%) rename src/class18/{Code05_ConvertToLetterString.java => Code04_ConvertToLetterString.java} (93%) create mode 100644 src/class18/Code05_StickersToSpellWord.java diff --git a/src/class18/Code01_RobotWalk.java b/src/class18/Code01_RobotWalk.java index db85fee..0ec8238 100644 --- a/src/class18/Code01_RobotWalk.java +++ b/src/class18/Code01_RobotWalk.java @@ -39,31 +39,26 @@ public class Code01_RobotWalk { // 走向左、走向右是截然不同的方法,所以总方法数要都算上 return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P); } - - - - - - + public static int waysCache(int N, int M, int K, int P) { // 参数无效直接返回0 if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { return 0; } - - int[][] dp = new int[N+1][K+1]; - for(int row = 0; row <= N; row++) { - for(int col = 0; col <= K; col++) { + + int[][] dp = new int[N + 1][K + 1]; + for (int row = 0; row <= N; row++) { + for (int col = 0; col <= K; col++) { dp[row][col] = -1; } } - return walkCache(N, M, K, P,dp); + return walkCache(N, M, K, P, dp); } - // HashMap (19,100) "19_100" + // HashMap (19,100) "19_100" // 我想把所有cur和rest的组合,返回的结果,加入到缓存里 public static int walkCache(int N, int cur, int rest, int P, int[][] dp) { - if(dp[cur][rest] != -1) { + if (dp[cur][rest] != -1) { return dp[cur][rest]; } if (rest == 0) { @@ -75,22 +70,12 @@ public class Code01_RobotWalk { return dp[cur][rest]; } if (cur == N) { - dp[cur][rest] =walkCache(N, N - 1, rest - 1, P,dp); + dp[cur][rest] = walkCache(N, N - 1, rest - 1, P, dp); return dp[cur][rest]; } - dp[cur][rest] = walkCache(N, cur + 1, rest - 1, P,dp) - + walkCache(N, cur - 1, rest - 1, P, dp); + dp[cur][rest] = walkCache(N, cur + 1, rest - 1, P, dp) + walkCache(N, cur - 1, rest - 1, P, dp); return dp[cur][rest]; } - - - - - - - - - public static int ways2(int N, int M, int K, int P) { // 参数无效直接返回0 diff --git a/src/class18/Code03_Knapsack.java b/src/class18/Code02_Knapsack.java similarity index 93% rename from src/class18/Code03_Knapsack.java rename to src/class18/Code02_Knapsack.java index c31945c..0bcb2e0 100644 --- a/src/class18/Code03_Knapsack.java +++ b/src/class18/Code02_Knapsack.java @@ -1,6 +1,6 @@ package class18; -public class Code03_Knapsack { +public class Code02_Knapsack { public static int getMaxValue(int[] w, int[] v, int bag) { return process(w, v, 0, 0, bag); @@ -44,7 +44,7 @@ public class Code03_Knapsack { int p1 = process(w, v, index + 1, rest); int p2 = -1; int p2Next = process(w, v, index + 1, rest - w[index]); - if(p2Next!=-1) { + if (p2Next != -1) { p2 = v[index] + p2Next; } return Math.max(p1, p2); @@ -56,9 +56,9 @@ public class Code03_Knapsack { // dp[N][...] = 0 for (int index = N - 1; index >= 0; index--) { for (int rest = 0; rest <= bag; rest++) { // rest < 0 - int p1 = dp[index+1][rest]; + int p1 = dp[index + 1][rest]; int p2 = -1; - if(rest - w[index] >= 0) { + if (rest - w[index] >= 0) { p2 = v[index] + dp[index + 1][rest - w[index]]; } dp[index][rest] = Math.max(p1, p2); diff --git a/src/class18/Code02_StickersToSpellWord.java b/src/class18/Code02_StickersToSpellWord.java deleted file mode 100644 index cc6ca43..0000000 --- a/src/class18/Code02_StickersToSpellWord.java +++ /dev/null @@ -1,152 +0,0 @@ -package class18; - -import java.util.Arrays; -import java.util.HashMap; - -public class Code02_StickersToSpellWord { - - public static int minStickers1(String[] stickers, String target) { - - int n = stickers.length; - - int[][] map = new int[n][26];// stickers -> [26] [26] [26] - for (int i = 0; i < n; i++) { - char[] str = stickers[i].toCharArray(); - for (char c : str) { - map[i][c - 'a']++; - } - } - HashMap dp = new HashMap<>(); - dp.put("", 0); - return process1(dp, map, target); - } - - // dp 傻缓存,如果t已经算过了,直接返回dp中的值 - // t 剩余的目标 - // 0..N每一个字符串所含字符的词频统计 - // 返回值是-1,map 中的贴纸 怎么都无法rest - public static int process1( - HashMap dp, - int[][] map, - String rest) { - if (dp.containsKey(rest)) { - return dp.get(rest); - } - // 以下就是正式的递归调用过程 - int ans = Integer.MAX_VALUE; // ans -> 搞定rest,使用的最少的贴纸数量 - int n = map.length; // N种贴纸 - int[] tmap = new int[26]; // tmap 去替代 rest - char[] target = rest.toCharArray(); - for (char c : target) { - tmap[c - 'a']++; - } - for (int i = 0; i < n; i++) { - // 枚举当前第一张贴纸是谁? - if (map[i][target[0] - 'a'] == 0) { - continue; - } - StringBuilder sb = new StringBuilder(); - // i 贴纸, j 枚举a~z字符 - for (int j = 0; j < 26; j++) { // - if (tmap[j] > 0) { // j这个字符是target需要的 - for (int k = 0; k < Math.max(0, tmap[j] - map[i][j]); k++) { - sb.append((char) ('a' + j)); - } - } - } - // sb -> i - String s = sb.toString(); - int tmp = process1(dp, map, s); - if (tmp != -1) { - ans = Math.min(ans, 1 + tmp); - } - } - // ans 系统最大 rest - dp.put(rest, ans == Integer.MAX_VALUE ? -1 : ans); - return dp.get(rest); - } - - public static int minStickers2(String[] stickers, String target) { - int n = stickers.length; - int[][] map = new int[n][26]; - for (int i = 0; i < n; i++) { - char[] str = stickers[i].toCharArray(); - for (char c : str) { - map[i][c - 'a']++; - } - } - char[] str = target.toCharArray(); - int[] tmap = new int[26]; - for (char c : str) { - tmap[c - 'a']++; - } - HashMap dp = new HashMap<>(); - int ans = process2(map, 0, tmap, dp); - return ans; - } - - public static int process2(int[][] map, int i, int[] tmap, HashMap dp) { - StringBuilder keyBuilder = new StringBuilder(); - keyBuilder.append(i + "_"); - for (int asc = 0; asc < 26; asc++) { - if (tmap[asc] != 0) { - keyBuilder.append((char) (asc + 'a') + "_" + tmap[asc] + "_"); - } - } - String key = keyBuilder.toString(); - if (dp.containsKey(key)) { - return dp.get(key); - } - boolean finish = true; - for (int asc = 0; asc < 26; asc++) { - if (tmap[asc] != 0) { - finish = false; - break; - } - } - if (finish) { - dp.put(key, 0); - return 0; - } - if (i == map.length) { - dp.put(key, -1); - return -1; - } - int maxZhang = 0; - for (int asc = 0; asc < 26; asc++) { - if (map[i][asc] != 0 && tmap[asc] != 0) { - maxZhang = Math.max(maxZhang, (tmap[asc] / map[i][asc]) + (tmap[asc] % map[i][asc] == 0 ? 0 : 1)); - } - } - int[] backup = Arrays.copyOf(tmap, tmap.length); - int min = Integer.MAX_VALUE; - int next = process2(map, i + 1, tmap, dp); - tmap = Arrays.copyOf(backup, backup.length); - if (next != -1) { - min = next; - } - for (int zhang = 1; zhang <= maxZhang; zhang++) { - for (int asc = 0; asc < 26; asc++) { - tmap[asc] = Math.max(0, tmap[asc] - (map[i][asc] * zhang)); - } - next = process2(map, i + 1, tmap, dp); - tmap = Arrays.copyOf(backup, backup.length); - if (next != -1) { - min = Math.min(min, zhang + next); - } - } - int ans = min == Integer.MAX_VALUE ? -1 : min; - dp.put(key, ans); - return ans; - } - - public static void main(String[] args) { - String[] arr = {"aaaa","bbaa","ccddd"}; - String str = "abcccccdddddbbbaaaaa"; - System.out.println(minStickers1(arr, str)); - System.out.println(minStickers2(arr, str)); - - - } - -} diff --git a/src/class18/Code04_CardsInLine.java b/src/class18/Code03_CardsInLine.java similarity index 97% rename from src/class18/Code04_CardsInLine.java rename to src/class18/Code03_CardsInLine.java index 40fb2ce..9d3c12c 100644 --- a/src/class18/Code04_CardsInLine.java +++ b/src/class18/Code03_CardsInLine.java @@ -1,6 +1,6 @@ package class18; -public class Code04_CardsInLine { +public class Code03_CardsInLine { public static int win1(int[] arr) { if (arr == null || arr.length == 0) { diff --git a/src/class18/Code05_ConvertToLetterString.java b/src/class18/Code04_ConvertToLetterString.java similarity index 93% rename from src/class18/Code05_ConvertToLetterString.java rename to src/class18/Code04_ConvertToLetterString.java index 608143a..a42d2a6 100644 --- a/src/class18/Code05_ConvertToLetterString.java +++ b/src/class18/Code04_ConvertToLetterString.java @@ -1,6 +1,6 @@ package class18; -public class Code05_ConvertToLetterString { +public class Code04_ConvertToLetterString { public static int number(String str) { if (str == null || str.length() == 0) { diff --git a/src/class18/Code05_StickersToSpellWord.java b/src/class18/Code05_StickersToSpellWord.java new file mode 100644 index 0000000..5e574c8 --- /dev/null +++ b/src/class18/Code05_StickersToSpellWord.java @@ -0,0 +1,140 @@ +package class18; + +import java.util.HashMap; + +// 本题测试链接:https://leetcode.com/problems/stickers-to-spell-word +public class Code05_StickersToSpellWord { + + public static int minStickers1(String[] stickers, String target) { + int ans = process1(stickers, target); + return ans == Integer.MAX_VALUE ? -1 : ans; + } + + public static int process1(String[] stickers, String target) { + if (target.length() == 0) { + return 0; + } + int min = Integer.MAX_VALUE; + for (String first : stickers) { + String rest = minus(target, first); + if (rest.length() != target.length()) { + min = Math.min(min, process1(stickers, rest)); + } + } + return min + (min == Integer.MAX_VALUE ? 0 : 1); + } + + public static String minus(String s1, String s2) { + char[] str1 = s1.toCharArray(); + char[] str2 = s2.toCharArray(); + int[] count = new int[26]; + for (char cha : str1) { + count[cha - 'a']++; + } + for (char cha : str2) { + count[cha - 'a']--; + } + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 26; i++) { + if (count[i] > 0) { + for (int j = 0; j < count[i]; j++) { + builder.append((char) (i + 'a')); + } + } + } + return builder.toString(); + } + + public static int minStickers2(String[] stickers, String target) { + int N = stickers.length; + // 关键优化(用词频表替代贴纸数组) + int[][] counts = new int[N][26]; + for (int i = 0; i < N; i++) { + char[] str = stickers[i].toCharArray(); + for (char cha : str) { + counts[i][cha - 'a']++; + } + } + int ans = process2(counts, target); + return ans == Integer.MAX_VALUE ? -1 : ans; + } + + public static int process2(int[][] stickers, String t) { + if (t.length() == 0) { + return 0; + } + char[] target = t.toCharArray(); + int[] tcounts = new int[26]; + for (char cha : target) { + tcounts[cha - 'a']++; + } + int N = stickers.length; + int min = Integer.MAX_VALUE; + for (int i = 0; i < N; i++) { + int[] sticker = stickers[i]; + // 关键优化(重要的剪枝!这一步也是贪心!) + if (sticker[target[0] - 'a'] > 0) { + StringBuilder builder = new StringBuilder(); + for (int j = 0; j < 26; j++) { + if (tcounts[j] > 0) { + int nums = tcounts[j] - sticker[j]; + for (int k = 0; k < nums; k++) { + builder.append((char) (j + 'a')); + } + } + } + String rest = builder.toString(); + min = Math.min(min, process2(stickers, rest)); + } + } + return min + (min == Integer.MAX_VALUE ? 0 : 1); + } + + public static int minStickers3(String[] stickers, String target) { + int N = stickers.length; + int[][] counts = new int[N][26]; + for (int i = 0; i < N; i++) { + char[] str = stickers[i].toCharArray(); + for (char cha : str) { + counts[i][cha - 'a']++; + } + } + HashMap dp = new HashMap<>(); + dp.put("", 0); + int ans = process3(counts, target, dp); + return ans == Integer.MAX_VALUE ? -1 : ans; + } + + public static int process3(int[][] stickers, String t, HashMap dp) { + if (dp.containsKey(t)) { + return dp.get(t); + } + char[] target = t.toCharArray(); + int[] tcounts = new int[26]; + for (char cha : target) { + tcounts[cha - 'a']++; + } + int N = stickers.length; + int min = Integer.MAX_VALUE; + for (int i = 0; i < N; i++) { + int[] sticker = stickers[i]; + if (sticker[target[0] - 'a'] > 0) { + StringBuilder builder = new StringBuilder(); + for (int j = 0; j < 26; j++) { + if (tcounts[j] > 0) { + int nums = tcounts[j] - sticker[j]; + for (int k = 0; k < nums; k++) { + builder.append((char) (j + 'a')); + } + } + } + String rest = builder.toString(); + min = Math.min(min, process3(stickers, rest, dp)); + } + } + int ans = min + (min == Integer.MAX_VALUE ? 0 : 1); + dp.put(t, ans); + return ans; + } + +}