diff --git a/readme.md b/readme.md index 9236566..045e4eb 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -## Algorithms (22/ 167) +## Algorithms (23/ 167) | Name | Tags | Solution | | --------------------------------------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | @@ -15,7 +15,7 @@ | Frequency Queries | `Hash Tables` | [TypeScript](./src/algorithms/hashtables/frequency-queries) | | Making Anagrams | `Strings` | [TypeScript](./src/algorithms/strings/make-anagram) | | Alternating Characters | `Strings` | [TypeScript](./src/algorithms/strings/alternating-characters) | -| Sherlock and the Valid String | `Strings` | | +| Sherlock and the Valid String | `Strings` | [TypeScript](./src/algorithms/strings/sherlock-and-the-valid-string) | | Special String Again | `Strings` | | | Common Child | `Strings` | | | Contains-Duplicate | `Arrays`, `Hash Tables` | [TypeScript](./src/algorithms/arrays_hashtables/contains-duplicate) | diff --git a/src/algorithms/strings/sherlock-and-the-valid-string/sherlock-and-the-valid-string..ts b/src/algorithms/strings/sherlock-and-the-valid-string/sherlock-and-the-valid-string..ts new file mode 100644 index 0000000..5a3f031 --- /dev/null +++ b/src/algorithms/strings/sherlock-and-the-valid-string/sherlock-and-the-valid-string..ts @@ -0,0 +1,54 @@ +/** + * + * Sherlock considers a string to be valid if all characters of the string appear the same number of times. + * It is also valid if he can remove just character at index in the string, and the remaining characters will occur the same number of times. + * Given a string , determine if it is valid. If so, return YES, otherwise return NO. + * + * + * Example: + * s = abc // => YES + * + * this is a valid string because frequencies are { a: 1, b: 1, c : 1} + * + * + * s = abccc // => NO + * + * This string is not valid as we can only remove 1 occurrence of c. That leaves character frequencies of { a: 1, b: 1, c : 2}. + * + */ + +export function isValid(s: string): string { + const charFrequency: Map = new Map() + + for (const char of s) { + charFrequency.set(char, (charFrequency.get(char) || 0) + 1) + } + + const frequencyCount: Map = new Map() + + for (const freq of charFrequency.values()) { + frequencyCount.set(freq, (frequencyCount.get(freq) || 0) + 1) + } + + const frequencies = Array.from(frequencyCount.keys()) + + if (frequencies.length === 1) return 'YES' + + if (frequencies.length === 2) { + const [f1, f2] = frequencies + const high = Math.max(f1, f2) + const low = Math.min(f1, f2) + + const highCount = frequencyCount.get(high) + const lowCount = frequencyCount.get(low) + + const oneCharHasFreqOne = low === 1 && lowCount === 1 + const oneCharHasExtra = high - low === 1 && highCount === 1 + + if (oneCharHasFreqOne || oneCharHasExtra) { + return 'YES' + } + } + + return 'NO' +} diff --git a/src/algorithms/strings/sherlock-and-the-valid-string/sherlock-and-the-valid-string.spec.ts b/src/algorithms/strings/sherlock-and-the-valid-string/sherlock-and-the-valid-string.spec.ts new file mode 100644 index 0000000..ebed413 --- /dev/null +++ b/src/algorithms/strings/sherlock-and-the-valid-string/sherlock-and-the-valid-string.spec.ts @@ -0,0 +1,31 @@ +import { isValid } from './sherlock-and-the-valid-string.' + +describe('isValid Sherlock', () => { + it("should return 'YES' for string with equal frequencies", () => { + expect(isValid('aabbcc')).toBe('YES') + }) + + it("should return 'YES' when one character can be removed to equalize frequencies", () => { + expect(isValid('aabbc')).toBe('YES') + }) + + it("should return 'NO' when more than one removal is needed", () => { + expect(isValid('aabbcd')).toBe('NO') + }) + + it("should return 'YES' when only one character has freq=1", () => { + expect(isValid('aaabbbcccd')).toBe('YES') + }) + + it("should return 'NO' when no valid removal can equalize frequencies", () => { + expect(isValid('aabbccddeefghi')).toBe('NO') + }) + + it("should return 'YES' for a string with all same character", () => { + expect(isValid('aaaa')).toBe('YES') + }) + + it("should return 'YES' for a single character", () => { + expect(isValid('z')).toBe('YES') + }) +})