[Leetcode] 回文问题
[2] Valid Palindrome
[4] Palindrome Partitioning II
[7] Longest Palindromic Substring
一、判断一个整数是否是回文
非常直接的方法,是将这个整数的高低位进行颠倒,然后判断数字是否是相等的。但是这样做的的一个缺点是可能会溢出,比如最大的整数是2147483647(32位),将其颠倒则为7463847412肯定溢出了,如何防止整数的溢出呢?
使用double进行运算。
如果不适用double进行运算,可以对整数进行对称的比较,首先计算整数的位数N。
while N>=2
high = num/pow(10,N-1)得到最高位
low = num%10得到最低位
判断之
num = (num%pow(10,N-1))/10;
N=N-2;
二、判断字符串是否是回文
"A man, a plan, a canal: Panama"
is a palindrome."race a car"
is not a palindrome.
Character.isLetterOrDigit(char)
三、划分的所有可能情况
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"] ]
使用递归遍历所有的划分情况是最好的选择。为了减少递归当中判断回味子串的复杂度,我们首先求出所有的回文子串。
求回文子串的长度,可以应用到 [7] 当中。使用动态规划的思想
flag[i][j]==true, 如果i==j,活着s(i)==s(j)并且(j==i+1||flag[i+1][j-1])
代码如下:
1 public class Solution { 2 private void DFS(List<List<String>> res, String s,int start, List<String> tmpstring, boolean[][]flag){ 3 if(start==s.length()){ 4 List<String> newlist = new LinkedList<String>(); 5 newlist.addAll(tmpstring); 6 res.add(newlist); 7 return; 8 } 9 for(int i=start;i<s.length();i++){ 10 if(flag[start][i]){ 11 String segment=s.substring(start,i+1); 12 tmpstring.add(segment); 13 DFS(res,s,i+1,tmpstring,flag); 14 tmpstring.remove(tmpstring.size()-1); 15 } 16 } 17 } 18 public List<List<String>> partition(String s) { 19 List<List<String>> res = new LinkedList<List<String>>(); 20 if(s==null||s.compareTo("")==0) return res; 21 boolean [][] flag = new boolean[s.length()][s.length()]; 22 for(int i=s.length()-1;i>=0;i--){ 23 for(int j=i;j<s.length();j++){ 24 if(i==j) { 25 flag[i][j]=true; 26 continue; 27 } 28 if(s.charAt(i)==s.charAt(j)){ 29 if(j==i+1||flag[i+1][j-1]) 30 flag[i][j]=true; 31 } 32 } 33 } 34 List<String> tmpstring = new LinkedList<String>(); 35 DFS(res,s,0,tmpstring,flag); 36 return res; 37 } 38 }
四、划分的最少次数
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab"
,
Return 1
since the palindrome partitioning ["aa","b"]
could be produced using 1 cut.
这里使用问题三当中的求取flag的方法,需要增加的代码是在每次划分的时候要更新最少的换发cut数
定义mincut[i]为从i开始到最后的子串所需的最少的cut数量。
具体还是要利用以往的子回文信息,如果从当前索引i,往右的j索引是回文,那么我们可以知道
mincut[i] = min(1+mincut[j+1],mincut[i]);
为什会要在检测到回文的时候进行更新?
存在的最少的划分方式,肯定是在各个回文的位置进行的划分,最极端的情况,每个单字符是一个回文,在不是回文的地方进行划分肯定不是最少的划分方式。
五、最短回文长度
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation.
For example:
Given "aacecaaa"
, return "aaacecaaa"
.
Given "abcd"
, return "dcbabcd"
.
字符串匹配
aacecaaa#aaacecaa
使用kmp算法得到最大前后缀为,可以得到aacecaa
然后在前面不辍多余的部分
aaacecaaa
六、链表回文判断
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
方法一、修改结构
首先将链表划分为两部分,根据长度的奇偶性,不同处理方式,即可。
然后将后者reverse,在进行判断,
最后在reverse回去。
最后回复链表。
方法二、递归
使用递归的方式挑战一些另外一种思路。
我们将head指向第一个节点,如果当前节点不是最后一个节点则继续递归,否则判断tail节点和head是否相等,若相等,head = head.next,同时递归返回,继续判断,有点类似从链表构造bst的赶脚。
1 public class Solution { 2 public ListNode ln; 3 public boolean isPalindrome(ListNode head) { 4 if(head==null || head.next==null){ 5 return true; 6 } 7 ln=head; 8 return isPalin(ln); 9 } 10 public boolean isPalin(ListNode nod){ 11 if(nod.next == null){ 12 return nod.val == ln.val; 13 } 14 boolean res = isPalin(nod.next); 15 ln=ln.next; 16 return res && nod.val==ln.val; 17 } 18 }
[1] https://leetcode.com/discuss/52441/java-recursive-solution
七、最长回文子字符串的问题
使用上面提到的方法