算法: 字符串回文大全

回文:把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。

1.题目:

给定一个字符串,问是否能通过添加一个字母将其变为回文串。

输入描述:
一行一个由小写字母构成的字符串,字符串长度小于等于10。
输出描述:
输出答案(YES\NO).
输入例子:
coco
输出例子:
YES

思路:

1.既然增加一个字符就是回文,那么同样减去一个字符也是回文。

2.普通思路:遍历字符串每个字符,删掉该字符并传入判断回文的函数。时间复杂度为O(N^2).

3.进阶思路:利用递归方法,从两边直接开始判断回文,传递一个变量来记录值能跳过一次两边不相等。时间复杂度O(n);


代码:


using System;
namespace 增加一个字符是否能成为回文串
{
    class Program
    {
        static void Main(string[] args)
        {
            string line;
            string[] p;
            while ((line = Console.ReadLine()) != null)
            {
                char[] str = line.Trim().ToCharArray();
                Console.WriteLine(helper(str,0,str.Length-1,false));
                Console.ReadLine();
            }
        }

        static bool helper(char[] str, int start, int end, bool flag)
        {
            if (start >= end)
                return true;
            if (str[start] == str[end])
            {
                return helper(str, start + 1, end - 1, flag);
            }
            else
            {
                if (flag)
                {
                    return false;
                }
                else
                {
                    return helper(str, start + 1, end, true) || helper(str, start, end - 1, true);
                }
            }
        }
    }
}


2.题目: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"]
 
思路:

1.用递归+动态规划方法实现

2.递归条件:当前字符串s分成两部分,一部分是回文,另一部分进行递归

3.递归返回后,删除上次添加的回文

代码:

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

3.题目: 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.


思路:

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

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

代码:

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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值