題目難度:Medium
做題日期:2017年3月21日
提交地址:https://leetcode.com/problems/palindrome-partitioning/#/description
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
[ ["aa","b"], ["a","a","b"]]
題目要求將一個字符串分成回文的組合,需要求出所有的符合要求的組合。比如字符串 aab 有兩種組合: aa, b 和 a, a, b。其中 aa, b, a 都是回文。
可以將問題分解成兩個子問題:如何分割字符串 和 判斷子串是否為回文。
判斷回文的方法
先說說簡單的問題:判斷回文的方法。
判斷回文有三種方法:雙指針、遞歸 和 Reverse 字符串。
雙指針是通過兩個指針,分別指向字符串的首尾,如果當前的兩個字符相等則繼續,直到兩個指針相遇(或者位置相差 1)。
def is_palindrome(s)
i, j = 0, s.length - 1
while i < j do
return false if s[i] != s[j]
i += 1
j += 1
end
return true
end
遞歸的思路跟雙指正類似:當前字符串是否為回文取決於首尾兩個字符是否相等 和 除去首尾兩個字符的子串是否為回文。
def is_palindrome(s)
return true if s.length == 0 || s.length == 1
s[0] == s[-1] && is_palindrome(s[1..-2])
end
Reverse 字符串的思路就是字符串反轉後判斷是否與原串相等,一般動態語言的字符串都有反轉字符串的API,所以代碼最簡單。
def is_palindrome(s)
s == s.reverse
end
如何分割字符串
分割字符串比較簡單,可以用兩種方式分割:其一,將字符串 AB 分割成 A + B連個字符串,會產生新的字符串,比如 abc 可以分割成 a + bc, ab + c, a + b + c;其二,用一個下標表示字符串的分割位置,這種方式沒有實際的分割字符串,只是用了一個標識位。
解決了上面的兩個問題,我們就可以做這道題了。
暴力回溯的思路比較簡單,如上面的分析所說,我們只需要窮舉字符串的所有子串的可能組合,去掉那些不符合要求的組合就可以了。
在窮舉所有的組合的時候,如果遇到當前分割的子串不是回文,則直接回溯。
非常感謝 五群的 @流風Susie 提供了如下的分析圖。
回溯算法最難理解的是回溯後,一定要把路徑中的上一個結果移除。
時間複雜度分析:
實例代碼
遞歸的思路跟暴力搜索有些許不同:將字符串分成 A + B兩個部分,如果 A 是回文,我們只需要求出 B 的所有回文的組合就行,然後將 A 和 B 結果做笛卡爾乘積就行了。
比如求 aaab 的所有回文組合:
將字符串分割成 a + aab, a 子串是回文, aab子串的回文組合是 [a, a, b], [aa, b], 所以合併組合: [a, a, a, b], [a, aa, b]
將字符串分割成 aa + ab, aa 子串是回文, ab 子串的回文組合是 [a, b], 所以合併組合: [aa, a, b]
... ...
遞推公式:
dp(j, i) = s[i] == s[j] && dp(j+1, i-1)
dp(j,i) 表示下標 j 到 下標 i 的子串是否是回文
長按下面的二維碼,關注每日一道算法題公眾號,跟我們一起學習算法!
群規
《每日一題算法群》群規
代碼規範
[每日一題]代碼規範v1.0
二分法相關的題目
[每日一題]二分法的三個區間控制套路
[每日一題]162. Find Peak Element
[每日一題]410. Split Array Largest Sum
[每日一題]209. Minimum Size Subarray Sum
[每日一題]240. Search a 2D Matrix II
[每日一題]74. Search a 2D Matrix
[每日一題]154. Find Minimum in Rotated Sorted Array II
[每日一題]174. Dungeon Game
數學相關的題目
[每日一題]264. Ugly Number II
[每日一題]202. Happy Number
[每日一題]172. Factorial Trailing Zeroes
[每日一題]483. Smallest Good Base
[每日一題]172. Factorial Trailing Zeroes
堆和棧
[周總結] stack 和 heap
[每日一題]402. Remove K Digits
[每日一題] 224. Basic Calculator
[每日一題]373. Find K Pairs with Smallest Sums
[每日一題]451. Sort Characters By Frequency
分治算法
[每日一題]分治算法(Divid and Conquer)總結
資源共享
[資源分享]分享一套清爽的Bootstrap UI 套件
[資源分享]Python算法進階之路
其他
面試心得
如何有效的區分小公司和創業公司
如何持續不斷的成長?