字符串操作之回文字符串 包含子字符串的最小窗口

版权声明:前半生,不害怕;后半生,不后悔! https://blog.csdn.net/qq_14842117/article/details/89220188

1.给一个字符串,寻找最长的回文子串
例如:输入babad 输出bab

动态规划做,虽然不如“马拉车”方法算法复杂度低,但是好理解呀。
建立一个boolean类型的数组 boolean[][] dp = new boolean[][];
dp[i][j]表示第i个字符到第j个字符是否是回文子串
1.如果i,j对应的字符相等,并且i,j之间的距离小于等于2.如aa,bb aba bcb这样的,显然是回文串
2.如果i,j对应的字符相等,并且dp[i+1][j-1]为true,则也是回文字符串
3.否则就不是

class Solution {
   public static String longestPalindrome(String s) {
    int len = s.length();
    if(s == null || len == 0){
        return s;
    }
    String res = "";
    int max = 0;
    //创建一个行列均为字符串长度的二维数组,创建时默认初始化为false
    boolean[][] dp = new boolean[len][len];
    for(int j = 0; j < len; j++){
        for(int i = 0; i <= j; i++){//这里只考虑了i<=j的情况,因为i>j时均为false
//当i==j,j-i==1,j-i==2时,只要满足s.charAt(i) == s.charAt(j)就是回文字符串
//如果不是这样,还要判断当前回文字符串的子串是不是回文字符串,即dp[i + 1][j - 1]),这就是动 
//态规划思想
            dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1]);
            if(dp[i][j]){//如果是回文字符串
                if(j - i + 1 > max){//并且比之前的回文字符串要长,更新字符串长度,记录字符串
                    max = j - i + 1;
                    res = s.substring(i, j + 1);
                }
            }
        }
    }
    return res;
    }
}

2.给定一个字符串S和字符串T,寻找S中最小的窗口包含T中所有的字符,时间复杂度要求O(n).

举例:
Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"
class Solution {
   public String minWindow(String s, String t) {
    if(s == null || s.length() < t.length() || s.length() == 0){
        return "";
    }
    HashMap<Character,Integer> map = new HashMap<Character,Integer>();
    //把字符串t中的字符放入map集合中
    for(char c : t.toCharArray()){
        if(map.containsKey(c)){
            map.put(c,map.get(c)+1);
        }else{
            map.put(c,1);
        }
    }
    int left = 0;
    int minLeft = 0;
    int minLen = s.length()+1;
    int count = 0;
    for(int right = 0; right < s.length(); right++){
    //如果map集合中包含该字符,个数减1,表示窗口中有了这个字符。
        if(map.containsKey(s.charAt(right))){
            map.put(s.charAt(right),map.get(s.charAt(right))-1);
            //只有map集合字符值大于等于0表示该值是有用的,为负表示该字符出现多了
            if(map.get(s.charAt(right)) >= 0){
                count ++;
            }
            while(count == t.length()){
                if(right-left+1 < minLen){
                    minLeft = left;
                    minLen = right-left+1;
                }
                //如果left所在位置包含在t字符串中,map集合值加1,表示在窗口中去掉这个字符,
                //找下个该字符
                if(map.containsKey(s.charAt(left))){
                    map.put(s.charAt(left),map.get(s.charAt(left))+1);
                    if(map.get(s.charAt(left)) > 0){
                        count --;
                    }
                }
                left ++ ;
            }
        }
    }
    if(minLen>s.length())  
    {  
        return "";  
    }  
    
    return s.substring(minLeft,minLeft+minLen);
}
}

猜你喜欢

转载自blog.csdn.net/qq_14842117/article/details/89220188