The cleanest way and fastest to do the second question is as follows.
- Keep track of all the "most recent" matching intervals seen so far for each alphabet pairs. There should be up to 26 pairs. Here's what most recent means. Say you have a pattern like "abcdaA", you would never want to pick the interval (0,5) for the a/A pair when you can pick interval (4,5). There is never a situation where interval (0,5) would result in a smaller balanced substring. This is the greedy intuition that nets up at most 26 intervals at any given point and everything falls into place.
- Loop from left to right, updating the list of most recent intervals for each alphabet.
- For any overlapping intervals, merge them together. You have up to 26 intervals, and you can do this in O(26*log(26)) time: see https://leetcode.com/problems/merge-intervals/ for inspiration (essentially sort by start, then merge).
- Loop through all 26 intervals, return the smallest value. Note that interval without a matching pair is infinity.
Time complexity: O(n * alphabet)
Space Complexity: O(alphabet)
pseudocode
int upper[26] = {INT_MIN};
int lower[26] = {INT_MIN};
int res=INT_MAX;
for(int i=0; i<arr.size(); i++) {
char c=arr[i];
if(isupper(c)) upper[c-'A']=i;
else lower[c-'a']=i;
map<int,int> m; //C++ ordered maps are sorted
for(int i=0; i<26; i++) m[min(upper[i],lower[i])]=max(upper[i],lower[i]);
// Now just find the smallest interval in a map, if you are confused, see https://leetcode.com/problems/merge-intervals/.
// for each interval, res=min(res,interval size);
}
return res;
Hope that helps since it looks like all the other posted solutions here have big edge cases and some are stupidly complicated. Honestly look me a bit to think of this. I can't imagine being able to come up with this in an time constrained situation.
Also - to all the people who says this is a simple sliding window problem / classic DP problem without providing a solution, screw you.