Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
I have came up with a solution that worked, but failed for several test cases. I then found a better solution and I rewrote it to try and understand it. The solution below works flawlessly, but after about 2 hours of battling with this thing, I still can not understand why this particular line of code works.
import java.util.*;
import java.math.*;
public class Solution {
public int lengthOfLongestSubstring(String str) {
if(str.length() == 0)
return 0;
HashMap<Character,Integer> map = new HashMap<>();
int startingIndexOfLongestSubstring = 0;
int max = 0;
for(int i = 0; i < str.length(); i++){
char currentChar = str.charAt(i);
if(map.containsKey(currentChar))
startingIndexOfLongestSubstring = Math.max(startingIndexOfLongestSubstring, map.get(currentChar) + 1);
map.put(currentChar, i);
max = Math.max(max, i - startingIndexOfLongestSubstring + 1);
}//End of loop
return max;
}
}
The line in question is
max = Math.max(max, i - startingIndexOfLongestSubstring + 1);
I don't understand why this works. We're taking the max between our previous max, and the difference between our current index and the starting index of what is currently the longest substring and then adding 1. I know that the code is getting the difference between our current index, and the startingIndexOfSubstring, but I can't conceptualize WHY it works to give us the intended result; Can someone please explain this step to me, particularly WHY it works?
I'm usually bad at explaining, let me give it a shot by considering an example.
String is "wcabcdeghi".
Forget the code for a minute and assume we're trying to come up with a logic.
map.put(currentChar, i);
)max
startingIndexOfLongestSubstring
to keep track of this. (This should've been named startingIndexOfNonRepetativeCharacter, then again I'm bad with naming as well).startingIndexOfNonRepetativeCharacter
) so to know the length of current sub-string all I need to do is (In code -)i - startingIndexOfLongestSubstring + 1
(current character position - The non-repetative character length + (subtraction doesn't do inclusive of both sides so adding 1). Lets call this currentLength
currentLength
can break our max.
So (In code -) max = Math.max(max, i - startingIndexOfLongestSubstring + 1);
startingIndexOfLongestSubstring = map.get(currentChar)
. So why are we doing a Max
?startingIndexOfLongestSubstring
).Hope I've answered all lines in the code and mainly If the explanation was understandable.