L5 判断一个字符串是不是回文串

判断一个字符串是不是回文串
如:aba是回文串

    /**
    *验证子串s[left ..right] 是否为回文串
    * char[] charArray:带判断的char型字符串
    * int left 最左端索引
    * int right 最右端索引
    */
    private boolean validPalindromic(char[] charArray,int left,int right){
        // 判断每一个charArray[left]是否与对应的charArray[right]相等
        // 如果有一个不相等的,直接返回false,否则 left++,right--,知道left 不再小于right
        // 如果判断完都没有false,那么直接返回true
        while(left < right){
            if(charArray[left] != charArray[right]){
                return false;
            }
            left++;
            right--;
        }
        //返回true
        return true;
        
    }
class Solution {
    
    //暴力解法
    /*
    *String s:待判断的字符串
    */
    public String longestPalindrome(String s) { 
        //获取字符串的长度
        int len = s.length();
        //如果长度是0或者1,那么直接返回字符串
        if(len <2){
            return s;
        }
        //如果字符串的长度>1
        //定义一个回文串的长度的初始值为1
        //定义回文串的初始索引为0
        int maxLen = 1;
        int begin = 0;
        
        //s.charAt(i)每次都会检查数组下标越界,因此先转换成字符数组,这一步非必须
        char[] charArray = s.toCharArray();
        
        //枚举所有长度严格大于1的子串 charArray[i...j]
        //定义两个变量i,j
        // i从0开始,j从i+1开始,判断charArray[i..j]是不是回文串,并记录最大回文串的起始位置
        // maxLen用于保存每一次遍历的最大回文串的长度,
        //begin用于保存最大回文串的初始索引
        //根据初始索引和最大长度,返回最大回文串
        for(int i=0;i<len -1;i++){
            for(int j=i+1;j<len;j++){
                if(j-i+1 > maxLen && validPalindromic(charArray,i,j)){
                    maxLen = j-i+1;
                    begin = i;
                }
            }
        }
        return s.substring(begin,begin+maxLen);

    }
    
    private boolean validPalindromic(char[] charArray,int left,int right){
        while(left < right){
            if(charArray[left] != charArray[right]){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
    
      
        
        
     
}

解法二:回文串

class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len <2){
            return s;
        }
        
        int maxLen = 1;
        int begin = 0;
        
        char[] charArray = s.toCharArray();
        for(int i=0;i<len -1;i++){
            int oddLen = expandAroundCenter(charArray,i,i);
            int evenLen = expandAroundCenter(charArray,i,i+1);
            
            int curMaxLen = Math.max(oddLen,evenLen);
            if(curMaxLen >maxLen){
                maxLen = curMaxLen;
                //这一步要在纸上画图发现规律
                begin = i-(maxLen -1) /2;
            }
        }
        return s.substring(begin,begin+maxLen);
    }
    
    //判断是否是回文串,中心扩散法,分奇偶数
    
    /** 
    * @param charArray 原始数组的字符数组
    * @param left 起始左边界
    * @param right 起始右边界
    * @return 回文串的长度
    */
    private int expandAroundCenter(char[] charArray,int left,int right){
        // 当left = right 的时候,回文中心是一个字符,回文串的长度是奇数
        // 当right = left + 1的时候,此时回文中心两个字符,回文串的长度是偶数
        int len = charArray.length;
        int i = left;
        int j = right;
        while(i>=0 && j<len){
            if(charArray[i] == charArray[j]){
                i--;
                j++;
            }else{
                break;
            }
        }
        //跳出while循环时,恰好满足s.charAt(i)!= s.charAt(j)
        //回文串的长度是j-i+1-2 = j-i-1
        return j-i-1;
        
    }
}

动态规划解法

package leetcode.editor.cn;

/**
 * 最长回文子串
 * @author Cao Ziqiang
 * @date 2022-09-07 09:19:59
 */
public class P5_LongestPalindromicSubstring{
	 public static void main(String[] args) {
	 	 //测试代码
	 	 Solution solution = new P5_LongestPalindromicSubstring().new Solution();
		  String s = solution.longestPalindrome("ab");
		 System.out.println(s);
	 }
	 
//代码
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public String longestPalindrome(String s) {
		//首先判断字符长度,小于2直接返回原字符串(空,一个字符)
		int len = s.length();
		if(len<2){
			return s;
		}
		//如果字符串个数>=2,初始化最大回文串的长度是1,因为就算两个字符串不同,那第一个字符串也是回文串,长度是1
		//初始化回文串的起始索引是0
		int maxLen = 1;
		int begin = 0;
		//初始化二维布尔数组dp[i][j]表示s[i..j]是否是回文串,行列都是字符串的长度,i是起始索引,j是终止索引
		//注意j>=i,因此只在二维数组的对角线及右上角是合法的,对角线是单个字符
		boolean[][] dp = new boolean[len][len];
		//初始化:长度为1的子串都是回文串,赋值为true
		for(int i = 0;i<len;i++){
			dp[i][i]= true;
		}
		//将字符串转为char型数组
		char[] charArray = s.toCharArray();

		//递推开始,感觉也是暴力搜索,只是优化一下
		//先枚举子串长度,长度为1的已经判断过了,现在判断长度为2的,然后依次增加
		//首先遍历所有长度为2的字符串,起始位置从0开始,长度为2, 然后向后移动一位,长度为2
		for(int L=2;L<=len;L++){
			//枚举左边界,左边界的上限设置可以宽松一些
			for(int i=0;i<len;i++){
				//由L和i可以确定右边界,即j-i+1 =L得
				int j = L +i -1;
				//如果右边界越界,就可以退出当前循环
				if(j >=len){
					break;
				}
				//如果ij对应的字符不相同,直接赋值dp[i][j] = false
				if(charArray[i] != charArray[j]){
					dp[i][j] = false;
				//否则,判读j-i的长度是否小于3,如果小于3,则直接赋值dp[i][j] = true
				//(因为,j-i<3意味着长度<=3,在这种情况下,两端的字符相同,则一定是回文串)
				//如果> 3则需要用到动态规划,判断其左下角的字符串是不是回文串	
				}else{
					if(j-i<3){
						dp[i][j] = true;
					}else{
						dp[i][j] = dp[i+1][j-1];
					}
				}
				//只要dp[i][j]==true成立,就表示子串s[i..j]是回文,此时记录回文长度和起始位置
				if(dp[i][j] && j-i+1 > maxLen){
					maxLen = j-i+1;
					begin = i;
				}
			}

		}
		//返回最大回文串
		return s.substring(begin,begin+maxLen);
	}
}
//leetcode submit region end(Prohibit modification and deletion)

}

ps:在条件判断中 and 是python中的,&&是java中表示关系与的,&是java中的位操作符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值