diff --git a/README.md b/README.md index 891cf72..d1b4c8e 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,7 @@ My approach to solving LeetCode problems typically involves the following steps: | 1657 | [Determine if Two Strings Are Close](https://leetcode.com/problems/determine-if-two-strings-are-close/) | Algorithms | [TypeScript](./problems/algorithms/determineIfTwoStringsAreClose/DetermineIfTwoStringsAreClose.ts) | Medium | | 2225 | [Find Players With Zero or One Losses](https://leetcode.com/problems/find-players-with-zero-or-one-losses/) | Algorithms | [TypeScript](./problems/algorithms/findPlayersWithZeroOrOneLosses/FindPlayersWithZeroOrOneLosses.ts) | Medium | | 380 | [Insert Delete GetRandom O(1)](https://leetcode.com/problems/insert-delete-getrandom-o1/) | Algorithms | [TypeScript](./problems/algorithms/insertDeleteGetrandomO1/InsertDeleteGetrandomO1.ts) | Medium | +| 1207 | [Unique Number of Occurrences](https://leetcode.com/problems/unique-number-of-occurrences/) | Algorithms | [TypeScript](./problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.ts) | Easy | | ... | ... | ... | ... | ... | In this table: diff --git a/problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.test.ts b/problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.test.ts new file mode 100644 index 0000000..bbed0c6 --- /dev/null +++ b/problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.test.ts @@ -0,0 +1,85 @@ +// Source : https://leetcode.com/problems/unique-number-of-occurrences/ +// Author : francisco +// Date : 2024-01-17 + +import { uniqueOccurrences } from "./UniqueNumberOfOccurrences"; + +describe("Unique Number of Occurrences", () => { + test("example 1", () => { + const result: boolean = uniqueOccurrences([1, 2, 2, 1, 1, 3]); + + expect(result).toBe(true); + }); + + test("example 2", () => { + const result: boolean = uniqueOccurrences([1, 2]); + + expect(result).toBe(false); + }); + + test("example 3", () => { + const result: boolean = uniqueOccurrences([ + -3, 0, 1, -3, 1, 1, 1, -3, 10, 0, + ]); + + expect(result).toBe(true); + }); + + test("additional testcase 4", () => { + const result: boolean = uniqueOccurrences([500]); + + expect(result).toBe(true); + }); + + test("additional testcase 5", () => { + const result: boolean = uniqueOccurrences([-987, -839]); + + expect(result).toBe(false); + }); + + test("additional testcase 6", () => { + const result: boolean = uniqueOccurrences([-399, -399]); + + expect(result).toBe(true); + }); + + test("additional testcase 7", () => { + const result: boolean = uniqueOccurrences([ + 26, 26, 26, 26, 26, 26, 26, 26, 26, 106, 117, 117, 117, 117, 117, 117, + 123, 123, 123, 123, 123, 123, 123, 123, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, + 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, + 390, 390, 390, 390, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 394, + 394, 394, 394, 474, 474, 474, 474, 474, 474, 474, 474, 474, 474, 561, 561, + 561, 561, 579, 579, 579, 579, 579, 579, 579, 579, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 687, 687, + 687, 687, 687, 687, 687, 798, 798, 804, 804, 804, 804, 804, 804, 804, 804, + 804, 804, 804, 804, 804, 804, 804, 804, 804, 892, 892, 892, 917, 917, 917, + 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, + ]); + + expect(result).toBe(false); + }); + + test("additional testcase 8", () => { + const result: boolean = uniqueOccurrences([ + 110, 110, 110, 110, 110, 110, 110, 110, 110, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 254, 254, 254, 254, 290, 290, 290, 290, 290, 290, 335, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, + 335, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, + 439, 514, 514, 514, 514, 514, 525, 525, 525, 525, 525, 525, 525, 525, 525, + 525, 525, 525, 525, 525, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 592, 592, 592, 592, 592, 592, 592, 592, 592, + 592, 592, 592, 592, 592, 592, 610, 610, 610, 610, 610, 610, 610, 610, 610, + 610, 610, 632, 632, 632, 686, 686, 686, 686, 686, 686, 686, 686, 686, 686, + 686, 686, 686, 686, 686, 686, 686, 686, 798, 813, 813, 813, 813, 813, 813, + 813, 813, 813, 813, 813, 813, 813, 821, 821, 821, 821, 821, 821, 821, 858, + 858, 858, 858, 858, 858, 858, 858, 915, 915, 982, 982, 982, 982, 982, 982, + 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, 982, + ]); + + expect(result).toBe(false); + }); +}); diff --git a/problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.ts b/problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.ts new file mode 100644 index 0000000..9ea8065 --- /dev/null +++ b/problems/algorithms/uniqueNumberOfOccurrences/UniqueNumberOfOccurrences.ts @@ -0,0 +1,91 @@ +// Source : https://leetcode.com/problems/unique-number-of-occurrences/ +// Author : francisco +// Date : 2024-01-17 + +/***************************************************************************************************** + * + * Given an array of integers arr, return true if the number of occurrences of each value in the array + * is unique or false otherwise. + * + * Example 1: + * + * Input: arr = [1,2,2,1,1,3] + * Output: true + * Explanation: The value 1 has 3 occurrences, 2 has 2 and 3 has 1. No two values have the same number + * of occurrences. + * + * Example 2: + * + * Input: arr = [1,2] + * Output: false + * + * Example 3: + * + * Input: arr = [-3,0,1,-3,1,1,1,-3,10,0] + * Output: true + * + * Constraints: + * + * 1 <= arr.length <= 1000 + * -1000 <= arr[i] <= 1000 + ******************************************************************************************************/ + +/** + * @param {number[]} arr + * @returns {boolean} + * return true if the number of occurrences of each value in the array is unique; false otherwise + + * Tests: + * I: arr = [1,2,2,1,1,3] -> O: true + * I: arr = [1,2] -> O: false + * I: arr = [-3,0,1,-3,1,1,1,-3,10,0] -> O: false + + * Template: + * hash -> occurrences + iteration arr + * occurrences array iteration + * to check for unique values - iterate through occurrences array and verify + + * Time Complexity: O(n), where n is arr.length + * Space Complexity: O(n) + */ +export function uniqueOccurrencesV1(arr: number[]): boolean { + const occurrencesHash: Record = {}; + + for (const num of arr) { + occurrencesHash[num] = (occurrencesHash[num] ?? 0) + 1; + } + + const occurrencesArr: number[] = Object.values(occurrencesHash); + + for (let index: number = 0; index < occurrencesArr.length; index++) { + if (index !== occurrencesArr.lastIndexOf(occurrencesArr[index] as number)) + return false; + } + + return true; +} + +// or for a better runtime + +/** + * @param {number[]} arr + * @returns {boolean} + * same purpose as previous function + + * Template: + * map for occurrences iterating through arr + * set for unique occurrences of map + * different way of checking for unique values (difference between map and set size) + + * Time Complexity: O(n), where n is arr.length + * Space Complexity: O(n) + */ +export function uniqueOccurrences(arr: number[]): boolean { + const occurrences = new Map(); + + for (const num of arr) occurrences.set(num, (occurrences.get(num) ?? 0) + 1); + + const uniqueOccurrences = new Set(occurrences.values()); + + return occurrences.size === uniqueOccurrences.size; +}