5. Longest Palindromic Substring
题目:找到一个字符串中最长的回文子串
思路:遍历字符串,看以下两种情况得到的子串是不是回文
public class Solution {
public String longestPalindrome(String s) {
String ret = new String();
int current = 0;
for(int i = 0; i < s.length(); i++){
if(isPalindrome(s,i-current-1,i)){
ret = s.substring(i-current-1,i+1);
current = current + 2;
}
else if(isPalindrome(s,i-current,i)){
ret = s.substring(i-current,i+1);
current ++;
}
}
return ret;
}
public boolean isPalindrome(String s,int start,int end){
if(start < 0 || end < 0 || start > s.length()-1 || end > s.length()-1) return false;
while(start < end){
if(s.charAt(start++) != s.charAt(end--)){
return false;
}
}
return true;
}
}
题目:找到最长回文子串的长度(不连续)
思路:动态规划——建立二维动态规划数组dp,分别存i到j子串的最长回文长度。对角线dp[i][i]均为1,对角线坐下角矩阵均为0,右上角矩阵从下到上慢慢扩散,最后计算出dp[0][s.length()-1]为输出结果。
public class Solution {
public int longestPalindromeSubseq(String s) {
int[][] dp =new int[s.length()][s.length()];
for(int i = s.length() - 1; i >= 0; i--){
dp[i][i] = 1;
for(int j = i+1; j < s.length(); j++){
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = dp[i+1][j-1] + 2;
}
else{
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][s.length()-1];
}
}
214. Shortest Palindrome
题目:在输入字符串前加入最少字符,使其成为一个回文串。
思路:暴力解法——从后往前看子串是否为回文串,是跳出将后面子串反序补到前面,实现没有问题,但是时间复杂度太高。
public class Solution {
public String shortestPalindrome(String s) {
int max = 0;
for(int i = s.length() - 1; i >= 0; i--){
if(isPalindrome(s.substring(0,i+1))){
max = i+1;
break;
}
}
if(max == s.length()) return s;
StringBuffer sb = new StringBuffer(s.substring(max, s.length()));
return sb.reverse().toString()+s;
}
public boolean isPalindrome(String s){
if(s.length() == 0) return false;
int i = 0, j = s.length() -1;
while(i<j){
if(s.charAt(i) != s.charAt(j)) return false;
i++;
j--;
}
return true;
}
}
KMP算法——没看懂,以后再补充
336. Palindrome Pairs
题目:
9. Palindrome Number
题目:判断一个整数是否为回文,不允许使用额外空间
思路:开始的想法是把整数的每一位打出来,再按位判断是否是回文,但是这样不满足不适用额外空间的要求。参考了别人的解法,这里记录一种比较巧妙的。将整数从个位开始的每一位拿出来,组成一个新的整数,相当于反转。但是当反转整数大于等于原整数的时候跳出循环,这样巧妙的避免了溢出的问题,也减少了运算量。(不过溢出的问题也可以通过long类型来解决)。另外需要注意的一点是,负数不是回文?个位是零的除了零以外都不是回文,因为输入整数第一位必不为零。
public class Solution {
public boolean isPalindrome(int x) {
if((x < 0)||(x != 0 && x%10==0)) return false;
int rev = 0;
while(x > rev){
rev = rev*10 + x%10;
x = x/10;
}
return (x == rev)||(x == rev/10);
}
}
234. Palindrome Linked List
题目:判断一个单向链表是不是回文,要求O(n)时间复杂度和O(1)空间复杂度
思路:Two Pointers——分为三步,第一,找到链表的中间节点,第二,反转后半部分链表,第三,比较前半部分链表和反转后的后半部分链表是否回文。这里在找中间节点的时候用到了快慢指针,遍历一次即可,以前喜欢先算出链表长度,再除2得到中间节点,这个毛病要改掉。
反转链表的过程想复杂了,简单过程如下:
对于1 -> 2,新建pre节点,取null
(1)1 -> 2
| |
head节点 next节点
(2)pre <- 1 2
(3)pre <- 1 2
| |
pre节点 head节点
head为空时跳出循环。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) return true;
if(head.next.next == null) return (head.val == head.next.val);
ListNode fast = head, slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
if(fast != null){
slow = slow.next;
}
ListNode pre = null;
while(slow != null){
ListNode next = slow.next;
slow.next = pre;
pre = slow;
slow = next;
}
slow = pre;
fast = head;
while(slow != null){
if(fast.val != slow.val) return false;
fast = fast.next;
slow = slow.next;
}
return true;
}
}