This is a popular question on LeetCode:
76. Minimum Window Substring
Given two strings s and t of lengths m and n respectively, return the minimum window substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "".
The testcases will be generated such that the answer is unique.
A substring is a contiguous sequence of characters within the string.
Example:
Input: s = "ADOBECODEBANC", t = "ABC"
Output: "BANC"
Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.
I converted the java solution provided by LeetCode to Swift since this is the language I am practicing in. Here is my code below:
func minWindowSlidingWindow(_ s: String, _ t: String) -> String { if s == t { return s } var uniqueCharacterHashTable: [Character: Int] = [:] for character in t { if let countOfChar = uniqueCharacterHashTable[character] { uniqueCharacterHashTable[character] = countOfChar + 1 continue } uniqueCharacterHashTable[character] = 1 } let uniqueCharactersRequired = uniqueCharacterHashTable.keys.count var uniqueCharactersFormed = 0 var currentWindowCharacterHashTable: [Character: Int] = [:] var minSequenceSize = Int.max var minimumSequenceStart = 0 var minimumSequenceEnd = 0 var currentStartIndexInt = 0 var currentEndIndexInt = 0 while currentEndIndexInt < s.count { let endIndex = s.index(s.startIndex, offsetBy: currentEndIndexInt) var currentCharacter = s[endIndex] if var characterCount = currentWindowCharacterHashTable[currentCharacter] { characterCount += 1 currentWindowCharacterHashTable[currentCharacter] = characterCount } else { currentWindowCharacterHashTable[currentCharacter] = 1 } if let _ = uniqueCharacterHashTable[currentCharacter], currentWindowCharacterHashTable[currentCharacter] == uniqueCharacterHashTable[currentCharacter] { uniqueCharactersFormed += 1 } while currentStartIndexInt <= currentEndIndexInt && uniqueCharactersFormed == uniqueCharactersRequired { let startIndex = s.index(s.startIndex, offsetBy: currentStartIndexInt) currentCharacter = s[startIndex] if minSequenceSize == Int.max || currentEndIndexInt - currentStartIndexInt + 1 < minSequenceSize { minSequenceSize = currentEndIndexInt - currentStartIndexInt + 1 minimumSequenceStart = currentStartIndexInt minimumSequenceEnd = currentEndIndexInt } if let characterCountInWindow = currentWindowCharacterHashTable[currentCharacter] { currentWindowCharacterHashTable[currentCharacter] = characterCountInWindow - 1 } if let _ = uniqueCharacterHashTable[currentCharacter], let currentCharOriginalCount = uniqueCharacterHashTable[currentCharacter], let charInWindowCount = currentWindowCharacterHashTable[currentCharacter], currentCharOriginalCount > charInWindowCount { uniqueCharactersFormed -= 1 } currentStartIndexInt += 1 } currentEndIndexInt += 1 } if minSequenceSize == Int.max { return "" } let startIndex = s.index(s.startIndex, offsetBy: minimumSequenceStart) let endIndex = s.index(s.startIndex, offsetBy: minimumSequenceEnd) return String(s[startIndex ... endIndex]) }
This works for the basic test cases and gives the desired output (as far as I know from about 10 test cases) but as the string size gets huge like 100,000 for example - it gets super slow even though I use the same data structures (I think) as suggested in the Java solution.
Can anyone point me as to where the bottleneck in this code lies and how could I optimize this further.