LeetCode 回文问题汇总:

     如果要求输出所有可能的解,使用深度优先搜索。如果要找出最优的解,或者解的数量,往往可以使用动态规划。

     关于回文问题的解决方案汇总如下,所有代码均已AC。

 

1.判断回文链表:(leetcode : Palindrome Linked List)

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?

      题解:定义快慢指针,将链表的前半部分放入到栈中,注意考虑奇数和偶数的情况,然后将依次读取链表的后半部分,与栈顶弹出的数字进行比较。另外,不建议将链表翻转,会造成头指针变化,比较翻转前后数据会出现问题。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/

import java.util.*;
public class Palindrome {
    public boolean isPalindrome(ListNode pHead) {
        //将链表中前半部分保存到栈中,定义快慢指针
        Stack<Integer> s = new Stack<Integer>();
        ListNode slow = pHead;
        ListNode fast = pHead;
        while( fast!=null && fast.next!=null){
            s.push(slow.val);
            slow = slow.next;
            fast = fast.next.next;
        }
        if(fast !=null)//奇数个时跳过中间数
            slow = slow.next;
        while(slow!=null){
            if(s.pop()!=slow.val)
                return false;
            slow = slow.next;
        }
        return true;
    }
}

 

2.判断是否为回文数字:(LeetCode:palindrome-number)

Determine whether an integer is a palindrome. Do this without extra space.

Some hints:

     Could negative integers be palindromes? (ie, -1).If you are thinking of converting the integer to string, note the restriction of using extra space.You could also try reversing an integer. However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. How would you handle such case?There is a more generic way of solving this problem.

      题解: 找到X的倒序数字,判断是否相等即可。

public class Solution {
    public boolean isPalindrome(int x) {
        if(x<0)
            return false;
        int reverse = 0;
        int num = x;
        while(x>0){
            reverse = reverse *10 + x%10;
            x /=10;
        }
        if(reverse == num)
            return true;
        else
            return false;
    }
}

 

3.判断字符串是否为回文字符串:(LeetCode:valid-palindrome)

       Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

For example,
"A man, a plan, a canal: Panama"is a palindrome.
"race a car"is not a palindrome.

Note:
       Have you consider that the string might be empty? This is a good question to ask during an interview.For the purpose of this problem, we define empty string as valid palindrome.

       题解:s.toLowerCase().replaceAll("[^0-9|a-z|]", "")过滤掉非数字、字母的字符。然后将字符串反转,判断反转后的字符串是否相等。

public class Solution {
    public boolean isPalindrome(String s) {
        if(s==null || s.length()==0)
            return true;
        s = s.toLowerCase().replaceAll("[^0-9|a-z|]", "");
        StringBuffer sb = new StringBuffer();
        sb.append(s);
        String temp = sb.reverse().toString();
        return s.equals(temp);
    }
}

 

4.回文串分割:(LeetCode:palindrome-partitioning)

          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"]
  ]   

        题解: 给定字符串s,分割s使得每个分区的字符串都是回文,求所有组合。全排列问题,使用dfs方式,在满足是回文的情况下进行dfs.

import java.util.*;
public class Solution {
    ArrayList<ArrayList<String>> result =
              new ArrayList<ArrayList<String>>();
    public ArrayList<ArrayList<String>> partition(String s) {
        ArrayList<String> list = new ArrayList<String>();
        dfs(s,0,list);
        return result;
    }
    public void dfs(String s,int index,ArrayList<String> list){
        if(index ==s.length()){
            result.add(new ArrayList<String>(list));
        }else{
            for(int i = index;i<s.length();i++){
                if(isPalindrome(s.substring(index,i+1))){
                    list.add(s.substring(index,i+1));
                    dfs(s,i+1,list);
                    list.remove(list.size()-1);
                }
            }
        }
    }
    public boolean isPalindrome(String str){
        boolean flag = true;
        int j = str.length()-1;
        int i = 0;
        while(i<j){
            if(str.charAt(i)!=str.charAt(j)){
                flag = false;
                break;
            }
            i++;j--;
        }
        return flag;
    }
}

 

5.回文串分割II:(LeetCode:palindrome-partitioning-ii)

         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",
Return1since the palindrome partitioning["aa","b"]could be produced using 1 cut.

给定字符串s,分割s使得每个分区的字符串都是回文,求最小分割次数。

解题思路:使用动态规划,dp[i] - 表示子串(0,i)的最小回文切割,则最优解在dp[s.length-1]中。

1.初始化:当字串s.substring(0,i+1)(包括i位置的字符)是回文时,dp[i] = 0(表示不需要分割);否则,dp[i] = i(表示至多分割i次);

2.对于任意大于1的i,如果s.substring(j,i+1)(j<=i,即遍历i之前的每个子串)是回文时,dp[i] = min(dp[i], dp[j-1]+1);

3.如果s.substring(j,i+1)(j<=i)不是回文时,dp[i] = min(dp[i],dp[j-1]+i+1-j);

public class Solution {
    public int minCut(String s) {
        int [] dp  = new int[s.length()];
        for(int i =0;i<s.length();i++){ 
            if(isPalindrome(s.substring(0,i+1))){
                dp[i]=0;
                continue;
            }else{
                 dp[i] = i; 
            }
            for(int j =1;j<=i;j++){
                String sub = s.substring(j,i+1);
                if(isPalindrome(sub)){
                    dp[i] =Math.min(dp[i],dp[j-1]+1);
                }else{
                    dp[i] = Math.min(dp[i],dp[j-1]+i+1-j);
                }
            }
        }
        return dp[s.length()-1];
    }
    public boolean isPalindrome(String str){
        boolean flag = true;
        int j = str.length()-1;
        int i = 0;
        while(i<j){
            if(str.charAt(i)!=str.charAt(j)){
                flag = false;
                break;
            }
            i++;j--;
        }
        return flag;
    }
}

 

6.最长回文子串:(LeetCode:longest-palindromic-substring)

       Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

      题解:遍历字符串,以字符串的该点为中心,向两边扩散,找到最长的回文子串,扩散寻找时,对以该点为中心的奇数回文串和偶数回文串分开判断。

import java.util.*;
public class Solution {
    public String longestPalindrome(String s) {
        //以该点为中心,向两边找以该点为中心的最长回文串
        if(s.length()==1)
            return s;
        int max = 1;
        String result = "";
        int index = 0;
        int start = 0;
        int count = 0;
        for(int i =0;i<s.length();i++){
            for(int j=0;(i-j)>=0 && (i+j)<s.length();j++){//奇数
                if(s.charAt(i-j)!=s.charAt(i+j))
                    break;
                index = j;
                count = 2*index+1;
            }
            if(max<count){
                max = count;
                start = i-index;
            }
            for(int j=0;(i-j)>=0 && (i+j+1)<s.length();j++){//偶数
                if(s.charAt(i-j)!=s.charAt(i+j+1))
                    break;
                index = j;
                count = 2*index+2;
            }
            if(max<count){
                max = count;
                start = i-index;
            }
        }
        result = s.substring(start,start+max);
        return result;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值