So I've been trying to solve a Leetcode Question, "Given a string, find the length of the longest substring without repeating characters."
For example
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Currently I optimized my algorithm when it comes to figuring out if the substring is unique by using a hash table. However my code still runs in O(n^2) runtime, and as a result exceeds the time limit during submissions.
What i try to do is to essentially go through every single possible substring and check if it has any duplicate values. Am I as efficient as it gets when it comes to the brute force method here? I know there's other methods such as a sliding window method but I'm trying to get the brute force method down first.
# @param {String} s
# @return {Integer}
def length_of_longest_substring(s)
max_length = 0
max_string = ""
n = s.length
for i in (0..n-1)
for j in (i..n-1)
substring = s[i..j]
#puts substring
if unique(substring)
if substring.length > max_length
max_length = substring.length
max_string = substring
end
end
end
end
return max_length
end
def unique(string)
hash = Hash.new(false)
array = string.split('')
array.each do |char|
if hash[char] == true
return false
else
hash[char] = true
end
end
return true
end
From your link:
That means you need first non-repeated substring.
I suggest here is such method
In Ruby < 2.6 use
[i..-1]
instead of[i..]
Approach
Here is a way of doing that with a hash that maps characters to indices. For a string
s
, suppose the characters in the substrings[j..j+n-1]
are unique, and therefore the substring is a candidate for the longest unique substring. The next element is thereforee = s[j+n]
We wish to determine ifs[j..j+n-1]
includese
. If it does not we can appende
to the substring, keeping it unique.If
s[j..j+n-1]
includese
, we determine ifn
(the size of the substring) is greater than the length of the previously-known substring, and update our records if it is. To determine ifs[j..j+n-1]
includese
, we could perform a linear search of the substring, but it is faster to maintain a hashc_to_i
whose key-value pairs ares[i]=>i
,i = j..j_n-1
. That is,c_to_i
maps the characters in the substring to their indices in full strings
. That way we can merely evaluatec_to_i.key?(e)
to see if the substring containse
. If the substring includese
, we usec_to_i
to determine its index ins
and add one:j = c_to_i[e] + 1
. The new substring is therefores[j..j+n-1]
with the new value ofj
. Note that several characters ofs
may be skipped in this step.Regardless of whether the substring contained
e
, we must now appende
to the (possibly-updated) substring, so that it becomess[j..j+n]
.Code
Example
Efficiency
Here is a benchmark comparison to @mechnicov's code:
displays: