LeetCode 940不同子序列II 递归解法单测通过连测失败问题问询
本题为LeetCode第940题:Distinct Subsequences II(不同子序列II)。
代码初始实现思路为:通过递归方式枚举所有子序列,使用HashSet对生成的子集去重,最终返回集合大小减1,排除题目要求不纳入统计的空字符串。
实际运行出现异常:单独运行单个测试用例时输出结果正常,连续批量运行测试用例时结果判定错误。
待确认两个问题:
- 错误原因是HashSet使用方式有误,还是递归逻辑本身存在问题
- 已知该题存在动态规划解法,仅确认本题是否存在可行的递归解法
相关参考材料共3份运行截图,分别为LeetCode平台代码编写截图、单测试用例运行结果截图、批量测试用例运行结果截图。
class Solution { static Set<String> myset = new HashSet<String>(0); public int distinctSubseqII(String s) { int i=0; String curr=""; subsets(s, curr, i); int val = myset.size()-1; return val; } public static void subsets(String str,String curr,int i){ if(i==str.length()){ //System.out.println(curr); myset.add(curr); return; } subsets(str, curr, i+1); subsets(str, curr+str.charAt(i), i+1); } }
错误根因
错误来自HashSet的使用方式,递归枚举子序列的基础逻辑本身没有问题。
代码中将存储子序列的myset定义为static静态变量,LeetCode批量执行测试用例时,不会为每个用例重新初始化Solution类,静态变量仅在类首次加载时初始化一次。上一个测试用例生成的所有子序列会一直残留在myset中,后续测试用例执行时会将历史残留内容一并统计,最终得到错误结果。
如果要修复批量运行报错的问题,只需将myset的初始化逻辑移到distinctSubseqII方法内部,每次方法调用时新建空的HashSet即可,不要使用static修饰该集合。
递归解法可行性
当前实现的暴力递归枚举所有子序列的逻辑虽然小数据量单测能跑通,但时间复杂度为O(2^n),字符串长度超过25左右就会出现严重超时,完全无法通过题目的全部测试用例,仅能处理长度极小的输入场景。
如果要实现可通过全部用例的递归解法,不能采用暴力枚举所有子序列存储字符串的思路,需要搭配记忆化存储、重复字符剪枝逻辑,本质是动态规划思路的递归实现,和当前暴力枚举的写法有本质差异。
内容的提问来源于stack exchange,提问作者Shilpa S

