I am trying to solve this question on LeetCode:
A string
s
is nice if, for every letter of the alphabet thats
contains, it appears both in uppercase and lowercase. For example, "abABB" is nice because 'A' and 'a' appear, and 'B' and 'b' appear. However, "abA" is not because 'b' appears, but 'B' does not.
Given a strings
, return the longest substring ofs
that is nice. If there are multiple, return the substring of the earliest occurrence. If there are none, return an empty string.
For s = "YazaAay", the expected output is: "aAa"
One of the top voted solutions uses a Divide and Conquer approach:
class Solution {
public String longestNiceSubstring(String s) {
if (s.length() < 2) return "";
char[] arr = s.toCharArray();
Set<Character> set = new HashSet<>();
for (char c: arr) set.add(c);
for (int i = 0; i < arr.length; i++) {
char c = arr[i];
if (set.contains(Character.toUpperCase(c)) && set.contains(Character.toLowerCase(c))) continue;
String sub1 = longestNiceSubstring(s.substring(0, i));
String sub2 = longestNiceSubstring(s.substring(i+1));
return sub1.length() >= sub2.length() ? sub1 : sub2;
}
return s;
}
}
I understand how it works, but not the intuition behind using a Divide and Conquer approach. In other words, if I revisit the problem again after a few days/weeks after I have forgotten everything about it, I won't be able to realize it is a Divide and Conquer problem.
What is that 'thing' that makes it solvable by a Divide and Conquer approach?
This is how the algorithm could be described in plain English:
If the entire string is nice, we are done.
Otherwise, there must be a character which exists in only one case. Such a character naturally divides the string into two substrings. Conquer each of them individually, and compare results.
Edit: BTW, I don't think it is a good example of D&C problem. The point is, once we encounter the first "bad" character, the substring to the left of it is nice. There is no need to descend into it. Just record its length and keep going. A simple loop it is.