Given a string s
. An awesome substring is a non-empty substring of s
such that we can make any number of swaps in order to make it palindrome.
Return the length of the maximum length awesome substring of s
.
Example 1:
Input: s = "3242415"
Output: 5
Explanation: "24241" is the longest awesome substring, we can form the palindrome "24142" with some swaps.
Example 2:
Input: s = "12345678"
Output: 1
Example 3:
Input: s = "213123"
Output: 6
Explanation: "213123" is the longest awesome substring, we can form the palindrome "231132" with some swaps.
Example 4:
Input: s = "00"
Output: 2
Constraints:
1 <= s.length <= 10^5
s
consists only of digits.
This problem is very similar with LeetCode 1371 in regard with the parity representation in a bitmask.
such a substring either has all even digit counts, or all even except one digit count that is odd. In fact, if we have a substring with all even counts and we have not reached the end of the input, we can always append 1 more character to make it longer. since we only care about the parity of each count and there are only 10 digits from 0 to 9, we can use bitmask + hash map to solve this problem. Keep a running bitmask that indicates each digit's parity, then we check for even length and odd length substrings. for even length, we only care about substring[0, i], because any other valid shorter substrings can be appended by 1 more character to make it be the odd case. If bitmask is 0, substring[0, i] is a valid answer candidate. for odd length, we check all 10 digits being the single odd count, and check if there is another bitmask with only this digit's value being different(even - even = even; odd - odd = even; even - odd = odd; odd - even = odd). If there is, we just found a odd length candidate. At last, if we have not seen the current bitmask before, save the mapping to the current index; otherwise we ignore it because we want to save the earliest appearance to get max length.
The runtime is O(10 * N), which is O(N).
class Solution { public int longestAwesome(String s) { Map<Integer, Integer> idxMap = new HashMap<>(); idxMap.put(0, -1); int best = 1; int curr = 0; for(int i = 0; i < s.length(); i++) { int diff = s.charAt(i) - '0'; int mask = 1 << diff; curr ^= mask; if(curr == 0) { best = Math.max(best, i + 1); } else { //try each digit as the odd count digit for(int j = 0; j <= 9; j++) { int k = 1 << j; int copy = curr; copy ^= k; if(idxMap.containsKey(copy)) { best = Math.max(best, i - idxMap.get(copy)); } } } if(!idxMap.containsKey(curr)) { idxMap.put(curr, i); } } return best; } }
Related Problems
[LeetCode 1371] Find the Longest Substring Containing Vowels in Even Counts