leetcode132 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.

Example:

Input: "aab"
Output: 1
Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.

首先看我的第一种解法:(废了很长时间,做题太少了,动脑太少了),这个运行时间蛮短的

package test;

public class LC132Try3
{
	public int minCut(String s)
	{
		int len = s.length();
		int[] dp = new int[len];
		char[] arr = s.toCharArray();
		//最多需要分j次
		for (int j = 0; j < len; j++)
		{
			dp[j] = j;
		}
		for (int i = 0; i < len; i++)
		{
			int m = i - 1;
			int n = i + 1;		
			
			while (m >= 0 && n < len)
			{

				if (arr[m] == arr[n])
				{
                    //如果是0则没有必要分割,不需要加1
					if (m == 0)
					{
						dp[n] = Math.min(dp[n], dp[m]);
					}
					else
					{
						dp[n] = Math.min(dp[n], dp[m - 1] + 1);
					}					

					m--;
					n++;
				}
				else
				{
					//如果和他后面的不相同,则更新下后面的,最多就是他前面的加1,防止他就是自己对应自己,自己单独分割
					dp[n] = Math.min(dp[n], dp[n-1] + 1);
					break;
				}
			}
			m = i;
			n = i + 1;
			while (m >= 0 && n < len)
			{
				if (arr[m] == arr[n])
				{

					if (m == 0)
					{
						dp[n] = Math.min(dp[n], dp[m]);
					}
					else
					{
						dp[n] = Math.min(dp[n], dp[m - 1] + 1);
					}					
					m--;
					n++;
				}
				else
				{
					dp[n] = Math.min(dp[n], dp[n-1] + 1);
					break;
				}
			}

		}

		return dp[len - 1];

	}

	public static void main(String[] args)
	{
		LC132Try3 t = new LC132Try3();
		System.out.println(t.minCut("aaa"));
		//System.out.println(t.minCut("eegiicgaeadbcfacfhifdbiehbgejcaeggcgbahfcajfhjjdgj"));
		// System.out.println(t.minCut("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));

	}

}

这种解法就是对应131图的解法,下面是图的另一种解法:这个也蛮烧脑的(just for me),不知道为什么他的运行时间更慢一点(这个就是左程云的回文最少分割数),我只是改成顺序了,但现在觉得还是逆序好。

package test;

public class LC132Try4
{
	public int minCut(String s)
	{
		int len = s.length();		
		if(s==null || len==0){
			return 0;
		}
		char[] arr= s.toCharArray();
		int[] cost=new int[len];
		boolean[][] dp=new boolean[len][len];
		for(int i=0;i<len;i++){//我这个是顺序,其实逆序更好,就不用判断j==0种情况了。
			cost[i]=i;
			for(int j=i;j>=0;j--){
				if(arr[j]==arr[i]&&( i-j<2 || dp[i-1][j+1] )){
					dp[j][i]=true;
					if(j==0){
						cost[i]=0;
					}else{
						cost[i]=Math.min(cost[i],cost[j-1]+1);
					}
					
				}
			}
		}
		return cost[len-1];
	}
	
	public static void main(String[] args)
	{
		LC132Try4 t = new LC132Try4();
		//System.out.println(t.minCut("aaa"));
		System.out.println(t.minCut("eegiicgaeadbcfacfhifdbiehbgejcaeggcgbahfcajfhjjdgj"));
		// System.out.println(t.minCut("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));

	}

}

这道题解法到此结束,哈哈,来看下,我的超时解法:

package test;


public class LC132Try2
{
	public int minCut(String s)
	{
		int len=s.length();
		int ret=len-1;
		if(len==0){
			return ret;
		}
		boolean[][] temp=new boolean[len][len];
		setPalindrome(s,temp,len);
		ret=getPalindrome(s,temp,len,0);
		return ret;
		
	}
	public int getPalindrome(String s,boolean[][] temp,int len,int start){
		if(start>=len){
			return 0;
		}
		int ret= len-start-1;
		for(int i=start;i<len;i++){			
			if(temp[start][i]){
				if(i==len-1){
					return 0;
				}
				int cost=getPalindrome(s,temp,len,i+1);
				ret=Math.min(ret, cost+1);
			}
		}
		return ret;
	}
	public void setPalindrome(String s,boolean[][] temp,int len){
		char[] arr= s.toCharArray();
		for(int i=0;i<len;i++){
			temp[i][i]=true;
			int m=i-1;//即以arr[i]为中间的回文;
			int n=i+1;
			while(m>=0&&n<len){
				if(arr[m]==arr[n]){
					temp[m][n]=true;
					m--;
					n++;
				}else{
					break;
				}
			}
			m=i;//与i对称的回文;
			n=i+1;
			while(m>=0&&n<len){
				if(arr[m]==arr[n]){
					temp[m][n]=true;
					m--;
					n++;
				}else{
					break;
				}
			}
		}
	}
	public static void main(String[] args)
	{
		LC132Try2 t = new LC132Try2();
		System.out.println(t.minCut("aba"));
		
	}

}

哈哈

package test;

import java.util.HashMap;
import java.util.Map;



public class LC132Try1
{
	public int minCut(String s)
	{
		Map<String,Integer> map = new HashMap<String,Integer>();
        int ret= minCost(s,map);
        return ret;
	}
	
	public int minCost(String s,Map<String,Integer> map)
	{
		if(map.containsKey(s)){
			return map.get(s);
		}
		int len = s.length();
		int ret = len - 1;		
		char[] arr=s.toCharArray();
		char c=arr[0];
		for(int i=0;i<arr.length;i++){
			if(arr[i]==c){
				String t=s.substring(0, i+1);
				if(isPalindrome(t)){
					if(i==arr.length-1){
						ret= 0;
					}else{
						int cost=minCost(s.substring(i+1),map);
						map.put(s.substring(i+1), cost);
						ret=Math.min(ret,cost+1) ;						
					}
									
				}
			}
		}
		return ret;

	}
	
	
	public boolean isPalindrome(String s){		
		int len=s.length();
		if(len==0){
			return false;
		}		
		char[] arr=s.toCharArray();
		for(int i=0;i<len/2;i++){
			if(arr[i]!=arr[len-i-1]){
				return false;
			}
		}
		return true;
	}
	
	
}

---2021年6月29日,另一种超时

class Solution {
    int min=2000;
    boolean[][] p1;
    public int minCut(String s) {
        int n=s.length();
        p1=new boolean[n][n];
        for(int k=n-1;k>=0;k--){
            p1[k][k]=true;
            for(int i=k+1;i<n;i++){//回文字符串的长度
                if(s.charAt(k)==s.charAt(i)&&(i-1<k+1||p1[k+1][i-1])){
                    p1[k][i]=true;
                }else{
                    p1[k][i]=false;
                }
            }

        }
        List<String> list=new ArrayList<>();
        getPass3(0,s,list);
        return min;


    }
    public void getPass3(int index,String s,List<String> list){
        if(index==s.length()){
            if(list.size()-1<min){
                min=list.size()-1;
            }
            return;
        }
        for(int j=index;j<s.length();j++){
            if(p1[index][j] && list.size()<=min){
                list.add(s.substring(index,j+1));
                getPass3(j+1,s,list);
                list.remove(list.size()-1);

            }

        }
    }
}

-----正常的递归:

public int minCut2(String s) {
        int n=s.length();
        int[] cost=new int[n];//
        boolean[][] p1=new boolean[n][n];
        for(int k=n-1;k>=0;k--){
            p1[k][k]=true;
            cost[k]=k;
            for(int i=k+1;i<n;i++){//回文字符串的长度
                if(s.charAt(k)==s.charAt(i)&&(i-1<k+1||p1[k+1][i-1])){
                    p1[k][i]=true;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=i;j<n;j++){
                if(p1[i][j]){
                    if(i==0){
                        cost[j]=0;
                    }else{
                        cost[j]=Math.min(cost[j],cost[i-1]+1);
                    }

                }

            }

        }
        return cost[n-1];
    }

哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值