From 0184b753b14e387ad42786a22e737288cf2f7167 Mon Sep 17 00:00:00 2001 From: aikhelis Date: Sat, 22 Feb 2025 23:28:26 +0000 Subject: [PATCH] ts-5: add sliding windows solutions --- .../longest_substring_with_unique_chars.ts | 20 +++++++++++++ ...t_substring_with_unique_chars_optimized.ts | 22 ++++++++++++++ ...st_uniform_substring_after_replacements.ts | 28 +++++++++++++++++ .../Sliding Windows/substring_anagrams.ts | 30 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 typescript/Sliding Windows/longest_substring_with_unique_chars.ts create mode 100644 typescript/Sliding Windows/longest_substring_with_unique_chars_optimized.ts create mode 100644 typescript/Sliding Windows/longest_uniform_substring_after_replacements.ts create mode 100644 typescript/Sliding Windows/substring_anagrams.ts diff --git a/typescript/Sliding Windows/longest_substring_with_unique_chars.ts b/typescript/Sliding Windows/longest_substring_with_unique_chars.ts new file mode 100644 index 0000000..1ff4968 --- /dev/null +++ b/typescript/Sliding Windows/longest_substring_with_unique_chars.ts @@ -0,0 +1,20 @@ +function longestSubstringWithUniqueChars(s: string): number { + let maxLen = 0; + let hashSet: Set = new Set(); + let left = 0, right = 0; + while(right < s.length) { + // If we encounter a duplicate character in the window, shrink + // the window until it's no longer a duplicate. + while(hashSet.has(s[right])){ + hashSet.delete(s[left]); + left++; + } + // Once there are no more duplicates in the window, update + // 'maxLen' if the current window is larger. + maxLen = Math.max(maxLen, right - left + 1); + hashSet.add(s[right]); + // Expand the window. + right++; + } + return maxLen; +} diff --git a/typescript/Sliding Windows/longest_substring_with_unique_chars_optimized.ts b/typescript/Sliding Windows/longest_substring_with_unique_chars_optimized.ts new file mode 100644 index 0000000..8bae80e --- /dev/null +++ b/typescript/Sliding Windows/longest_substring_with_unique_chars_optimized.ts @@ -0,0 +1,22 @@ +function longestSubstringWithUniqueCharsOptimized(s: string): number { + let maxLen = 0; + let prevIndexes: { [key: string]: number } = {}; + let left = 0, right = 0; + while(right < s.length) { + // If a previous index of the current character is present + // in the current window, it's a duplicate character in the + // window. + if (prevIndexes[s[right]] !== undefined + && prevIndexes[s[right]] >= left) { + // Shrink the window to exclude the previous occurrence + // of this character. + left = prevIndexes[s[right]] + 1; + } + // Update 'maxLen' if the current window is larger. + maxLen = Math.max(maxLen, right - left + 1); + prevIndexes[s[right]] = right; + // Expand the window. + right++; + } + return maxLen; +} diff --git a/typescript/Sliding Windows/longest_uniform_substring_after_replacements.ts b/typescript/Sliding Windows/longest_uniform_substring_after_replacements.ts new file mode 100644 index 0000000..33ca4ca --- /dev/null +++ b/typescript/Sliding Windows/longest_uniform_substring_after_replacements.ts @@ -0,0 +1,28 @@ +function longestUniformSubstringAfterReplacements(s: string, k: number): number { + const freqs: { [key: string]: number } = {}; + let highestFreq = 0, maxLen = 0; + let left = 0, right = 0; + while (right < s.length) { + // Update the frequency of the character at the right pointer + // and the highest frequency for the current window. + freqs[s[right]] = (freqs[s[right]] || 0) + 1; + highestFreq = Math.max(highestFreq, freqs[s[right]]); + // Calculate replacements needed for the current window. + const numCharsToReplace = (right - left + 1) - highestFreq; + // Slide the window if the number of replacements needed exceeds + // 'k'. The right pointer always gets advanced, so we just need + // to advance 'left'. + if (numCharsToReplace > k) { + // Remove the character at the left pointer from the hash map + // before advancing the left pointer. + freqs[s[left]]--; + left++; + } + // Since the length of the current window increases or stays the + // same, assign the length of the current window to 'maxLen'. + maxLen = right - left + 1; + // Expand the window. + right++; + } + return maxLen; +} diff --git a/typescript/Sliding Windows/substring_anagrams.ts b/typescript/Sliding Windows/substring_anagrams.ts new file mode 100644 index 0000000..4e0be45 --- /dev/null +++ b/typescript/Sliding Windows/substring_anagrams.ts @@ -0,0 +1,30 @@ +function substringAnagrams(s: string, t: string): number { + const lenS = s.length, lenT = t.length; + if (lenT > lenS) + return 0; + let count = 0; + const expectedFreqs = new Array(26).fill(0); + const windowFreqs = new Array(26).fill(0); + // Populate 'expected_freqs' with the characters in string 't'. + for (const c of t) + expectedFreqs[c.charCodeAt(0) - 'a'.charCodeAt(0)]++; + let left = 0, right = 0; + while (right < lenS) { + // Add the character at the right pointer to 'window_freqs' + // before sliding the window. + windowFreqs[s[right].charCodeAt(0) - 'a'.charCodeAt(0)]++; + // If the window has reached the expected fixed length, we + // advance the left pointer as well as the right pointer to + // slide the window. + if (right - left + 1 === lenT) { + if (windowFreqs.every((val, i) => val === expectedFreqs[i])) + count++; + // Remove the character at the left pointer from + // 'window_freqs' before advancing the left pointer. + windowFreqs[s[left].charCodeAt(0) - 'a'.charCodeAt(0)]--; + left++; + } + right++; + } + return count; +}