题目地址(131. 分割回文串)

https://leetcode-cn.com/problems/palindrome-partitioning/

题目描述

  1. 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
  2. 回文串 是正着读和反着读都一样的字符串。
  3. 示例 1
  4. 输入:s = "aab"
  5. 输出:[["a","a","b"],["aa","b"]]
  6. 示例 2
  7. 输入:s = "a"
  8. 输出:[["a"]]
  9. 提示:
  10. 1 <= s.length <= 16
  11. s 仅由小写英文字母组成

前置知识


公司

  • 暂无

思路

本题这涉及到两个关键问题:

  1. 切割问题,有不同的切割方式
  2. 判断回文

其实切割问题类似组合问题。
例如对于字符串abcdef:

  • 组合问题:选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中在选组第三个…..。
  • 切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中在切割第三段…..。

image.png
判断回文子串
最后我们看一下回文子串要如何判断了,判断一个字符串是否是回文。

可以使用双指针法,一个指针从前向后,一个指针从后先前,如果前后指针所指向的元素是相等的,就是回文字符串了。

关键点

  • 怎么判断是不是回文串
    • 双指针对向遍历
  • 递归如何终止
    • 起始位置大于s的大小

代码

  • 语言支持:Java

Java Code:

  1. class Solution {
  2. ArrayList<List<String>> res = new ArrayList<>();
  3. ArrayList<String> path = new ArrayList<>();
  4. // Deque<String> path = new LinkedList<>();
  5. public List<List<String>> partition(String s) {
  6. loop(s,0);
  7. return res;
  8. }
  9. void loop(String s , int startIndex){
  10. //终止条件 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
  11. if (startIndex >= s.length()) {
  12. res.add(new ArrayList<>(path));
  13. return;
  14. }
  15. //从0开始 循环数组长度次
  16. for (int i = startIndex; i < s.length() ; i++) {
  17. //判断是不是回文数 如果是 就把当前的与层数对应的字符串截取 然后添加到路径
  18. //如果不是 就跳过当次循环 第一次碰到就是把单个字符判断成回文串 递归回来在判断后面的
  19. if (judge(s, startIndex, i)) {
  20. path.add(s.substring(startIndex, i+1));
  21. }else {
  22. continue;
  23. }
  24. //递归 下一层由i+1来作为startIndex
  25. loop(s,i+1);
  26. //回溯 递归后返回将最后一个数删了
  27. path.remove(path.size()-1);
  28. }
  29. }
  30. //使用双指针 从前后分别遍历 如果遇到不相等的情况就返回false 其他都为true
  31. boolean judge(String s,int start , int end){
  32. for (int i = start , j = end ; i < j ; i++ , j--) {
  33. if (s.charAt(i) != s.charAt(j)) {
  34. return false;
  35. }
  36. }
  37. return true;
  38. }
  39. }

复杂度分析

令 n 为数组长度。

  • 时间复杂度:131. 分割回文串 - 图2#card=math&code=O%28n%29&id=ffdK2)
  • 空间复杂度:131. 分割回文串 - 图3#card=math&code=O%28n%29&id=u5hWn)