diff --git a/README.md b/README.md index 535c254..e96a192 100644 --- a/README.md +++ b/README.md @@ -88,4 +88,5 @@ - Sliding Window - [Task #15](src/neetcode/sliding-window/best-time-to-buy-and-sell-stock) – _Best Time To Buy And Sell Stock_ - _[check the task](https://neetcode.io/problems/buy-and-sell-crypto)_ - [Task #16](src/neetcode/sliding-window/longest-substring-without-repeating-characters) – _Longest Substring Without Repeating Characters_ - _[check the task](https://neetcode.io/problems/longest-substring-without-duplicates)_ - - [Task #17](src/neetcode/sliding-window/longest-repeating-character-replacement) – _Longest Repeating Character Replacement_ - _[check the task](https://neetcode.io/problems/longest-repeating-substring-with-replacement)_ \ No newline at end of file + - [Task #17](src/neetcode/sliding-window/longest-repeating-character-replacement) – _Longest Repeating Character Replacement_ - _[check the task](https://neetcode.io/problems/longest-repeating-substring-with-replacement)_ + - [Task #18](src/neetcode/sliding-window/permutation-in-string) – _Permutation In String_ - _[check the task](https://neetcode.io/problems/permutation-string)_ \ No newline at end of file diff --git a/src/neetcode/sliding-window/permutation-in-string/solution.test.ts b/src/neetcode/sliding-window/permutation-in-string/solution.test.ts new file mode 100644 index 0000000..2c22048 --- /dev/null +++ b/src/neetcode/sliding-window/permutation-in-string/solution.test.ts @@ -0,0 +1,33 @@ +import { checkInclusion } from './solution'; + +describe('Permutation In String | NeetCode | RoadMap | Testcases', () => { + test('#1 Permutation exists', () => { + const s1 = 'abc'; + const s2 = 'lecabee'; + expect(checkInclusion(s1, s2)).toBe(true); + }); + + test('#2 Permutation does not exist', () => { + const s1 = 'abc'; + const s2 = 'lecaabee'; + expect(checkInclusion(s1, s2)).toBe(false); + }); + + test('#3 Window will not be initialized', () => { + const s1 = 'ab'; + const s2 = 'eidboaoo'; + expect(checkInclusion(s1, s2)).toBe(false); + }); + + test('#4 Repeated needed chars', () => { + const s1 = 'adc'; + const s2 = 'dcda'; + expect(checkInclusion(s1, s2)).toBe(true); + }); + + test('#5 Repeated needed chars', () => { + const s1 = 'hello'; + const s2 = 'ooolleoooleh'; + expect(checkInclusion(s1, s2)).toBe(false); + }); +}); diff --git a/src/neetcode/sliding-window/permutation-in-string/solution.ts b/src/neetcode/sliding-window/permutation-in-string/solution.ts new file mode 100644 index 0000000..b71641c --- /dev/null +++ b/src/neetcode/sliding-window/permutation-in-string/solution.ts @@ -0,0 +1,36 @@ +/** + * @param {string} s1 + * @param {string} s2 + * @return {boolean} `true` if `s2` contains a permutation of `s1`, or `false` otherwise. + * That means if a permutation of `s1` exists as a substring of `s2` + */ +export const checkInclusion = (s1: string, s2: string): boolean => { + if (s1.length > s2.length) { + return false; + } + + const s1Chars: Record = {}; + for (const ch of s1) { + s1Chars[ch] = (s1Chars[ch] ?? 0) + 1; + } + + let l = 0; + let r = 0; + + const s2Chars: Record = {}; + + while (r - l !== s1.length) { + if (r === s2.length) { + return false; + } + s2Chars[s2[r]] = (s2Chars[s2[r]] ?? 0) + 1; + while ((s1Chars[s2[r]] ?? 0) < (s2Chars[s2[r]] ?? 0)) { + const count = s2Chars[s2[l]] ?? 0; + s2Chars[s2[l]] = count > 0 ? count - 1 : 0; + l++; + } + r++; + } + + return true; +};