一、知识点:
递归、回溯
二、文字分析:
算法思路:
- 首先,定义一个全局变量result来保存所有的分组方案,使用回溯的方法递归生成所有的合法分组。
- 在回溯的过程中,通过判断子串是否为回文串,将合法的子串加入当前分组,并递归处理剩下的部分。
- 当递归处理到字符串末尾时,说明找到了一个合法的分组方案,将当前分组加入到结果集中。
时间复杂度:
- 在最坏情况下,当输入字符串s为一个完全相同的字符时,例如"aaaaa",无法找到任何回文分组。此时需要生成2^n个分组方案,其中n为字符串长度。因此,时间复杂度为O(2^n)。
- 在平均情况下,时间复杂度介于最好和最坏情况之间,取决于具体的输入字符串。
空间复杂度:
- 除了结果集外,主要的空间消耗为递归调用时的栈空间和临时分组列表。栈空间的消耗取决于递归的深度,即生成的分组方案的数量。临时分组列表的空间消耗为O(n),其中n为字符串长度。
- 因此,空间复杂度为O(2^n + n)。
三、编程语言:
java
四、正确代码:
import java.util.*; public class Solution { private List<List<String>> result; public String[][] partition(String s) { result = new ArrayList<>(); // 初始化结果集 backtracking(s, new ArrayList<>(), 0); // 调用回溯函数 return convertToArray(result); // 将结果集转换为数组并返回 } public void backtracking(String s, List<String> group, int start) { if (start == s.length()) { // 当start等于字符串长度时,说明找到了一个合法的分组方案 result.add(new ArrayList<>(group)); // 将当前分组加入结果集 return; } for (int i = start; i < s.length(); i++) { String substring = s.substring(start, i + 1); // 获取从start到i的子串 if (isPalindrome(substring)) { // 如果子串是回文串 group.add(substring); // 将子串加入当前分组 backtracking(s, group, i + 1); // 递归处理剩下的部分,从位置i+1到字符串末尾的子串 group.remove(group.size() - 1); // 回溯,移除最后加入的子串 } } } public boolean isPalindrome(String s) { int left = 0; int right = s.length() - 1; while (left < right) { // 判断子串是否为回文串 if (s.charAt(left) != s.charAt(right)) { return false; } left++; right--; } return true; } public String[][] convertToArray(List<List<String>> list) { int m = list.size(); String[][] array = new String[m][]; for (int i = 0; i < m; i++) { // 遍历结果集中的每个分组 List<String> group = list.get(i); int n = group.size(); array[i] = new String[n]; for (int j = 0; j < n; j++) { // 将分组中的字符串保存到数组中 array[i][j] = group.get(j); } } return array; } }