1177.can-make-palindrome-from-substring-en

Problem

https://leetcode.com/problems/can-make-palindrome-from-substring/

Problem Description

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.

思路

In this problem, there are 2 conditions for checking whether substring is palindrome:

  • Rearrange, very useful here. e.g:abb can be rearranged to palindrome string bab, itself maybe not palindrome, but after rearrange, can be palindrome.

  • Can replace with at most K letters, meaning itself or after rearrange itself still cannot become palindrome, it may be palindrome after replacing K letters. e.g: abcd, k = 2,can replacecd -> ba, to be palindromeabba; or replaceab -> dc, be palindrome dccd

e.g: abcd, k = 1,then no matter how to replace, it cannot become palindrome.

After analysis, found there is some pattern to form palindrome by rearranging and replace K letters.

If we calculate the number of letters, and track the odd number letters, as oddCounts, if oddCounts/2 >= K then we can through replace K letters to form a new palindrome string, otherwise false.

Then this problem becomes to calculate the number of the letter which appears odd times in a substring, queries give us range, so range prefix sum is useful in this case (so that for each given range, we can get the number in ~O(1) time).

Steps:

  1. Define prefix sum matrix: prefixCount[i][j] keep track of in string s, in range [0, i] aka, in s[0,i], the number of letter j.

  2. Count the number of letters which appears odd number times (oddCounts) in range [start, end]. oddCounts += prefixCount[end+1][currChar] - prefixcount[start][currChar]

  3. If oddCounts/2 >= K, then substring can become palindrome after rearrange and replace <=Kletters.

  4. If oddCounts/2 < K, then substring cannot become palindrome, return false;.

As below pic, create a prefix sum matrix, prefixCount[i][j], since string only contains 26 lowercase letters, it is O(1) for loop 26 letters.

1177 can make palindrome

Complexity Analysis

  • Time Complexity: O(n + m * 26) - n is s length, m is queries length

  • Space Complexity: O(n * 26) - n is s length, n * 26 prefixcount matrix

Note, here we can also use HashMap,so that we don't need to loop 26 letters each time, only loop the number of letters in substring.

Validate a String is Palindrome

Palindrome String: forward and backward are exactly the same, e.g: madam,noon, 12321, aaaa etc.

Validate Palindrome Solution:

  1. Solution #1: Reverse string s, then check whether original string equals to reversed string. return s == reverse(s)

  2. Solution #2: use left and right two pointers, (left, right)left start from index 0, right from last index,when (left < right), compare

    -s[left] == s[right], then continue next, left move right, left++, right move left, right--

    • s[left] != s[right],then return false

Key Points

  • prefix sum matrix count index from 0 to i substring, the number of times that j letter appears

  • For each query, count the number of letters which appears odd times (oddCounts) in range [start, end], then compare oddCounts and k

Code (Java/Python3)

Java code

Python3 code (slow :( )

Last updated

Was this helpful?