From 0afa0e2e5dc0b32d38d766d81d73a6acca87cd46 Mon Sep 17 00:00:00 2001 From: Lusina <12752833+BrianLusina@users.noreply.github.com> Date: Tue, 27 Jan 2026 09:15:09 +0300 Subject: [PATCH 1/2] feat(algorithms, hash-table): first unique character --- .../first_unique_character/README.md | 35 +++++++++++++++++++ .../first_unique_character/__init__.py | 10 ++++++ .../test_first_unique_character.py | 26 ++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 algorithms/hash_table/first_unique_character/README.md create mode 100644 algorithms/hash_table/first_unique_character/__init__.py create mode 100644 algorithms/hash_table/first_unique_character/test_first_unique_character.py diff --git a/algorithms/hash_table/first_unique_character/README.md b/algorithms/hash_table/first_unique_character/README.md new file mode 100644 index 00000000..ec405a28 --- /dev/null +++ b/algorithms/hash_table/first_unique_character/README.md @@ -0,0 +1,35 @@ +# First Unique Character + +Given a string s, find the first non-repeating character in it and return its index. If it does not exist, return -1. + +## Examples + +Example 1: + +```text +Input: s = "leetcode" +Output: 0 +Explanation: +The character 'l' at index 0 is the first character that does not occur at any other index. +``` + +Example 2: + +```text +Input: s = "loveleetcode" +Output: 2 +``` + +Example 3: + +```text +Input: s = "aabb" +Output: -1 +``` + +## Constraints + +- 1 <= `s.length` <= 10^5 +- `s` consists of lowercase English letters +- There are no spaces in the string. + diff --git a/algorithms/hash_table/first_unique_character/__init__.py b/algorithms/hash_table/first_unique_character/__init__.py new file mode 100644 index 00000000..3f21e352 --- /dev/null +++ b/algorithms/hash_table/first_unique_character/__init__.py @@ -0,0 +1,10 @@ +from collections import Counter + + +def first_unique_character(s: str) -> int: + frequency = Counter(s) + + for idx, letter in enumerate(s): + if frequency[letter] == 1: + return idx + return -1 diff --git a/algorithms/hash_table/first_unique_character/test_first_unique_character.py b/algorithms/hash_table/first_unique_character/test_first_unique_character.py new file mode 100644 index 00000000..fd375be9 --- /dev/null +++ b/algorithms/hash_table/first_unique_character/test_first_unique_character.py @@ -0,0 +1,26 @@ +import unittest +from parameterized import parameterized +from algorithms.hash_table.first_unique_character import first_unique_character + +FIRST_UNIQUE_CHARACTER_TEST_CASES = [ + ("leetcode", 0), + ("loveleetcode", 2), + ("aabb", -1), + ("baefeab", 3), + ("aabbcc", -1), + ("dajhfiuebdafsdhdgaj", 5), + ("xyurtwxwtryua", 12), + ("aeiouqwertyauieotweryqq", -1), + ("awsjuhfajwfnkag", 2), +] + + +class FirstUniqueCharacterTestCase(unittest.TestCase): + @parameterized.expand(FIRST_UNIQUE_CHARACTER_TEST_CASES) + def test_first_unique_character(self, s: str, expected: int): + actual = first_unique_character(s) + self.assertEqual(expected, actual) + + +if __name__ == '__main__': + unittest.main() From 0eb558cdbd69f690d7e610af352e8e284ac648cb Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:15:37 +0000 Subject: [PATCH 2/2] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 9fc52691..491f4d62 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -166,6 +166,8 @@ * Two City Scheduling * [Test Two City Scheduling](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/greedy/two_city_scheduling/test_two_city_scheduling.py) * Hash Table + * First Unique Character + * [Test First Unique Character](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/hash_table/first_unique_character/test_first_unique_character.py) * Ransom Note * [Test Ransom Note](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/hash_table/ransom_note/test_ransom_note.py) * Heap