如何使用Java Streams求解字符串字母大小写全排列回溯问题
Java Streams 实现字母大小写全排列的落地方法
你卡壳的两个点,本质上是普通map操作的能力边界问题,完全不用硬套回溯的递归思路,顺着Java Streams的设计特性就能直接实现:
- 单字符双形态映射的实现逻辑
普通map是严格的1对1转换,一次输入只能输出一个结果,这也是你之前连续写两次大小写转换逻辑失效的核心原因:两次串联的map是顺序覆盖关系,先把所有元素转成大写、再把转完的全转回小写,最终只剩全小写的单条结果,根本生成不出大小写组合。
要实现一个字符映射出多个形态的效果,必须用flatMap做一对多的转换:对单个字符,判断是否为字母,如果是就生成包含小写、大写两个元素的流,非字母就只生成包含自身的单元素流,再把所有分散的流拍平展开。 - 流处理过程中逐段拼接的实现逻辑
逐字符拼接本质是状态累积的过程,不需要把每个字符单独处理后再硬凑拼接顺序,可以用reduce的累积特性完成:从仅包含空字符串的初始流开始,每处理一个字符,就把当前流里所有已经拼到一半的前缀字符串,和当前字符的所有可选形态逐一拼接,生成新的、更长的半完成字符串流,等所有字符处理完,流里剩下的就是全部符合要求的完整结果。
可直接运行的实现代码
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class Solution { public List<String> letterCasePermutation(String S) { return Arrays.stream(S.split("")) .reduce( // 初始累积状态:空字符串,代表还没拼接任何字符 Stream.of(""), (currentPrefixStream, currentChar) -> { // 计算当前字符的所有可选形态 Stream<String> charOptions = Character.isLetter(currentChar.charAt(0)) ? Stream.of(currentChar.toLowerCase(), currentChar.toUpperCase()) : Stream.of(currentChar); // 把已有前缀和每个字符选项拼接,拍平成新的累积流 return currentPrefixStream.flatMap(prefix -> charOptions.map(option -> prefix + option) ); }, // 并行场景下的流合并逻辑,串行执行时不会触发 Stream::concat ) .collect(Collectors.toList()); } }
实际效果验证
对输入"a1b2"执行上述代码,最终输出结果和题目要求完全一致:["a1b2","a1B2","A1b2","A1B2"]
这个实现的分支选择逻辑和传统回溯法完全等价,只是把递归栈里存储的半完成字符串状态,换成了流累积器中存储的所有分支前缀,全程用流操作完成全流程处理。
内容的提问来源于stack exchange,提问作者Jay Singh
相关产品推荐
相关产品推荐

