From d285d3d6b812a607bc31501a73a50a63222398d3 Mon Sep 17 00:00:00 2001 From: Younglesszzz <61218410+Younglesszzz@users.noreply.github.com> Date: Sun, 6 Mar 2022 20:54:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BA=86=E5=9B=9E=E6=BA=AF+?= =?UTF-8?q?=E8=AE=B0=E5=BF=86=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 经过提交验证,其实memo[startIndex] = 1的这个逻辑根本没有用到,因为如果返回true,那么会如同dfs一样直接返回,不会再进行下一步的backtracking搜索,本题的记忆法核心是令memo[startIndex]置为-1,来避免从相同的startIndex开始拆分,导致程序进行大量重复运算,这应该也是本题剪枝方法的核心。 --- problems/0139.单词拆分.md | 38 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/problems/0139.单词拆分.md b/problems/0139.单词拆分.md index 1653a81a..a54b849a 100644 --- a/problems/0139.单词拆分.md +++ b/problems/0139.单词拆分.md @@ -251,30 +251,34 @@ class Solution { // 回溯法+记忆化 class Solution { + private Set set; + private int[] memo; public boolean wordBreak(String s, List wordDict) { - Set wordDictSet = new HashSet(wordDict); - int[] memory = new int[s.length()]; - return backTrack(s, wordDictSet, 0, memory); + memo = new int[s.length()]; + set = new HashSet<>(wordDict); + return backtracking(s, 0); } - - public boolean backTrack(String s, Set wordDictSet, int startIndex, int[] memory) { - // 结束条件 - if (startIndex >= s.length()) { + + public boolean backtracking(String s, int startIndex) { + // System.out.println(startIndex); + if (startIndex == s.length()) { return true; } - if (memory[startIndex] != 0) { - // 此处认为:memory[i] = 1 表示可以拼出i 及以后的字符子串, memory[i] = -1 表示不能 - return memory[startIndex] == 1 ? true : false; + if (memo[startIndex] == -1) { + return false; } - for (int i = startIndex; i < s.length(); ++i) { - // 处理 递归 回溯 循环不变量:[startIndex, i + 1) - String word = s.substring(startIndex, i + 1); - if (wordDictSet.contains(word) && backTrack(s, wordDictSet, i + 1, memory)) { - memory[startIndex] = 1; - return true; + + for (int i = startIndex; i < s.length(); i++) { + String sub = s.substring(startIndex, i + 1); + // 拆分出来的单词无法匹配 + if (!set.contains(sub)) { + continue; } + boolean res = backtracking(s, i + 1); + if (res) return true; } - memory[startIndex] = -1; + // 这里是关键,找遍了startIndex~s.length()也没能完全匹配,标记从startIndex开始不能找到 + memo[startIndex] = -1; return false; } }