刷题记录-leetcodeP132 分割回文串Ⅱ(动态规划 java版)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串

返回符合要求的 最少分割次数 。

示例 1:

输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例 2:

输入:s = "a"
输出:0

示例 3:

输入:s = "ab"
输出:1

解题思路:动态规划

首先在这题中我们定义一个ans[]数组,ans[i]表示前i个字符满足题目条件的最少切割次数。我们知道单一字符一定是一个回文串,因此ans[1]=0。对于ans[2],考虑前两个字符的情况,如果这两个字符组成的字符串是回文串那么ans[2]=0,如果不是回文串,那么对这两个字符组成的字符串进行切割,切割为两个单一字符,第一个单一字符的切割次数就是ans[1],后面单一字符也一定是回文串,只需要+1即可,即ans[2]=ans[1]+1;综合这两种情况我们可以得出ans[2]=min(ans[1]+1,0);

ans[3]考虑前三个字符的情况,如果整体是回文串,那么ans[3]=0;如果不是,那么将这三个字符切割,这里有两种切割方法,1 | 23和12 | 3,第一种切割方式就需要判断23是否为回文串;第二种切割方式就是ans[2]+1……

整体流程:
     * 1、先判断整个字符串是否为回文串,是那么就是0
      * 2、ans[i]=min(ans[j]+1) j<i
      *       意思是:如①ans[4] 需要考虑ans[3]+1、② ans[2]和后面两个字符是否为回文(是的话就+1,不是就不能这么分)③ans[1]和后面三个字符是否问回文(同理)
       *3、在2的基础上,比对最小的即是ans[4]的值

依据这种情况,我们能够得出状态转移方程

j<i && [j+1,i]是回文串: ans[i] = min(ans[j]+1)

[1,i]是回文串: ans[i]=0;

	// 最小切割次数
    public static int minCut(String s) {
    	int n=s.length();
    	if(n == 0 ) return 0;
    	if(judge(s,0,n-1)) return 0; // 如果整体都是回文串,那么返回0
    	int []ans=new int[n+1]; // 定义ans数组:ans[i]表示前i个字符最小的分割次数
    	for(int i=1;i<=n;i++){
    		ans[i]=i-1; //初始化为最大次数
    	}
    	
    	for(int i=2;i<=n;i++){
    		// 整体为回文串
    		if(judge(s,0,i-1)){
    			ans[i]=0;
    			continue;
    		}
    		// 如果不是那么进行下面判断
    		//j<i && [j+1,i]这几个字符是否为 回文串

    		for(int j=1;j<i;j++){
    			if(judge(s,j,i-1)){
    				ans[i]=Math.min(ans[i], ans[j]+1);
    			}
    		}
    	}
    	return ans[n];
    	
    }
    // 用来判断是否是回文串
    public static boolean judge(String s,int start,int end){
    	while(start<end){
    		if(s.charAt(start)!=s.charAt(end)){
    			return false;
    		}else{
    			start++;
    			end--;
    		}
    	}
    	return true;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值