[leetcode]5175. Can Make Palindrome from Substring

一、题意

Given a string s, we make queries on substrings of s.

For each query queries[i] = [left, right, k], we may rearrange the substring s[left], ..., s[right], and then choose up to k of them to replace with any lowercase English letter. 

If the substring is possible to be a palindrome string after the operations above, the result of the query is true. Otherwise, the result is false.

Return an array answer[], where answer[i] is the result of the i-th query queries[i].

Note that: Each letter is counted individually for replacement so if for example s[left..right] = "aaa", and k = 2, we can only replace two of the letters.  (Also, note that the initial string s is never modified by any query.)

 

Example :

Input: s = "abcda", queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]]
Output: [true,false,false,true,true]
Explanation:
queries[0] : substring = "d", is palidrome.
queries[1] : substring = "bc", is not palidrome.
queries[2] : substring = "abcd", is not palidrome after replacing only 1 character.
queries[3] : substring = "abcd", could be changed to "abba" which is palidrome. Also this can be changed to "baab" first rearrange it "bacd" then replace "cd" with "ab".
queries[4] : substring = "abcda", could be changed to "abcba" which is palidrome.
 

Constraints:

1 <= s.length, queries.length <= 10^5
0 <= queries[i][0] <= queries[i][1] < s.length
0 <= queries[i][2] <= s.length
s only contains lowercase English letters.

二、题解

题意:给出一个字符串s,一个待检测串queries[i],每个queries[i]包含三个整数left、right、k。对子串s[left]....s[right]重新排列,同时最多可以更换k个字符,如果能排列成回文字符串则返回true,不然返回false;

样例解释:对于样例:s="abcda" , queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]]

  • queries[0] : substring = "d", 直接是回文字符串,不必更换字符
  • queries[1] : substring = "bc",重新排列不能变成回文字符串,最少更换1个字符才能变成回文字符串,然而k=0,所以返回false
  • queries[2] : substring = "abcd", 重新排列不能变成回文字符串,最少更换2个字符才能变成回文字符串,然而k=1,所以返回fasle
  • queries[3] : substring = "abcd", 重新排列不能变成回文字符串,最少更换1个字符才能变成回文,k=2大于1,所以返回true;
  • queries[4] : substring = "abcda", 重新排列不能变成回文字符串,最少更换1个字符才能变成回文,k=1大于等于1,所以返回true;

题解:

首先对于是否可以重新排列组成回文串的判定:

可以得出,假如字符串中有n种字符为奇数,那么最少需要更换n/2个字符才能满足重新排列变成回文串。(证明略)

对于每个queries[i],可以统计对应子串中只有奇数个的字符的种类数,设为n,若n/2>k那么返回fasle,不然返回true。

如果使用遍历统计子串中奇数个的字符的种类数会超时,这里借鉴博客https://www.cnblogs.com/oldhands/p/11442566.html中的算法,使用dp[i][j]数组,表示截止下标i,字符'a'+j的个数,那么在统计s[left]...s[right]中各种字符的个数时使用dp[right][j]-dp[left-1][j]即可。

AC代码:

class Solution {
public:
    vector<bool> canMakePaliQueries(string s, vector<vector<int>>& queries) {
        
        vector<bool>  ans;
        vector<vector<int> > dp(s.length(), vector<int>(26, 0)); 
    
        //dp[i][j] 截止i位置,字符a+j的个数
        for(int i=0; i<s.length(); i++){
            if(i==0){
                dp[i][s[0]-'a'] ++;
                continue;
            }else{
                for(int j=0; j<26; j++){
                    if(j==s[i]-'a'){
                        dp[i][j] = dp[i-1][j] +1;
                    }else{
                        dp[i][j] = dp[i-1][j];
                    }
                    //dp[j][]
                }
                //dp[i][s[i]-'a'] = dp[i-1][s[i]-'a']+1;
            }
        }
        /*
        for(int i=0; i<dp.size(); i++){
            for(int j=0; j<dp[i].size(); j++){
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }
        */
        for(int i=0; i<queries.size(); i++){
            //string temp = s.substr(queries[i][0], queries[i][1]-queries[i][0]+1);
            int left = queries[i][0];
            int right = queries[i][1];
            int k = queries[i][2];
            
            if(left==right || k>=(right-left+1)){
                ans.push_back(true);
                //cout<<"i:"<<i<<endl;
                continue;
            }
            
            int cnt = 0;
            
            for(int i=0; i<26; i++){
                if(left==0){
                    if(dp[right][i] % 2 == 1){
                        cnt ++;
                    }
                }else{
                    if((dp[right][i]-dp[left-1][i])%2 == 1){
                        cnt ++;
                    }
                }
            }
            cnt /= 2;
            //cout<<"i:"<<i<<" ";
            //cout<<cnt<<endl;
            if(cnt > k){
                ans.push_back(false);
            }else{
                ans.push_back(true);
            }
        }
        return ans;
        
    }
};

 

posted on 2019-09-01 17:52  刘好念  阅读(5)  评论(0)    收藏  举报  来源