From 5baee6ea855625c1e3a6c518daa6ef45ff035da3 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 3 Mar 2026 04:36:13 -0600 Subject: [PATCH] adding algo --- .../common_algos/two_sum_round_2.py | 21 +++++ .../common_algos/valid_palindrome_round_2.py | 22 ++++++ .../ex_92_word_ladder.py | 63 +++++++++++++++ .../ex_92_word_ladder.ts | 75 ++++++++++++++++++ .../test_92_word_ladder_round_22.py | 79 +++++++++++++++++++ 5 files changed, 260 insertions(+) create mode 100644 src/my_project/interviews/amazon_high_frequency_23/common_algos/two_sum_round_2.py create mode 100644 src/my_project/interviews/amazon_high_frequency_23/common_algos/valid_palindrome_round_2.py create mode 100644 src/my_project/interviews/top_150_questions_round_22/ex_92_word_ladder.py create mode 100644 src/my_project/interviews_typescript/top_150_questions_round_1/ex_92_word_ladder.ts create mode 100644 tests/test_150_questions_round_22/test_92_word_ladder_round_22.py diff --git a/src/my_project/interviews/amazon_high_frequency_23/common_algos/two_sum_round_2.py b/src/my_project/interviews/amazon_high_frequency_23/common_algos/two_sum_round_2.py new file mode 100644 index 00000000..2f204310 --- /dev/null +++ b/src/my_project/interviews/amazon_high_frequency_23/common_algos/two_sum_round_2.py @@ -0,0 +1,21 @@ +from typing import List, Union, Collection, Mapping, Optional +from abc import ABC, abstractmethod + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + + answer = dict() + + for k, v in enumerate(nums): + + if v in answer: + return [answer[v], k] + else: + answer[target - v] = k + + return [] + + + + + diff --git a/src/my_project/interviews/amazon_high_frequency_23/common_algos/valid_palindrome_round_2.py b/src/my_project/interviews/amazon_high_frequency_23/common_algos/valid_palindrome_round_2.py new file mode 100644 index 00000000..8bfb7f9e --- /dev/null +++ b/src/my_project/interviews/amazon_high_frequency_23/common_algos/valid_palindrome_round_2.py @@ -0,0 +1,22 @@ +from typing import List, Union, Collection, Mapping, Optional +from abc import ABC, abstractmethod +import re + +class Solution: + def isPalindrome(self, s: str) -> bool: + + # To lowercase + s = s.lower() + + # Remove non-alphanumeric characters + s = re.sub(pattern=r'[^a-zA-Z0-9]', repl='', string=s) + + # Determine if s is palindrome or not + len_s = len(s) + + for i in range(len_s//2): + + if s[i] != s[len_s - 1 - i]: + return False + + return True diff --git a/src/my_project/interviews/top_150_questions_round_22/ex_92_word_ladder.py b/src/my_project/interviews/top_150_questions_round_22/ex_92_word_ladder.py new file mode 100644 index 00000000..2ac18ee9 --- /dev/null +++ b/src/my_project/interviews/top_150_questions_round_22/ex_92_word_ladder.py @@ -0,0 +1,63 @@ +from typing import List, Union, Collection, Mapping, Optional +from abc import ABC, abstractmethod +from collections import deque, defaultdict + +class Solution: + def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: + """ + Find the shortest transformation sequence from beginWord to endWord. + Uses BFS to find the shortest path. + + Time Complexity: O(M^2 * N) where M is word length, N is wordList size + Space Complexity: O(M^2 * N) for the pattern dictionary + """ + # If beginWord equals endWord, the sequence is just the word itself + if beginWord == endWord: + return 1 + + # If endWord is not in wordList, no valid transformation exists + if endWord not in wordList: + return 0 + + # Convert wordList to set for O(1) lookup + word_set = set(wordList) + + # Build a pattern dictionary to find all words that differ by one letter + # e.g., "hot" -> {"*ot": ["hot"], "h*t": ["hot"], "ho*": ["hot"]} + pattern_dict = defaultdict(list) + word_len = len(beginWord) + + # Add beginWord to the set if not present + if beginWord not in word_set: + word_set.add(beginWord) + + # Create patterns for all words + for word in word_set: + for i in range(word_len): + pattern = word[:i] + '*' + word[i+1:] + pattern_dict[pattern].append(word) + + # BFS to find shortest path + queue = deque([(beginWord, 1)]) # (current_word, level) + visited = {beginWord} + + while queue: + current_word, level = queue.popleft() + + # Try all possible transformations by replacing each character + for i in range(word_len): + pattern = current_word[:i] + '*' + current_word[i+1:] + + # Get all words matching this pattern + for next_word in pattern_dict[pattern]: + if next_word == endWord: + return level + 1 + + if next_word not in visited: + visited.add(next_word) + queue.append((next_word, level + 1)) + + # Clear the pattern to avoid revisiting in future iterations + pattern_dict[pattern] = [] + + return 0 \ No newline at end of file diff --git a/src/my_project/interviews_typescript/top_150_questions_round_1/ex_92_word_ladder.ts b/src/my_project/interviews_typescript/top_150_questions_round_1/ex_92_word_ladder.ts new file mode 100644 index 00000000..fa3046fa --- /dev/null +++ b/src/my_project/interviews_typescript/top_150_questions_round_1/ex_92_word_ladder.ts @@ -0,0 +1,75 @@ +function ladderLength(beginWord: string, endWord: string, wordList: string[]): number { + /** + * Find the shortest transformation sequence from beginWord to endWord. + * Uses BFS to find the shortest path. + * + * Time Complexity: O(M^2 * N) where M is word length, N is wordList size + * Space Complexity: O(M^2 * N) for the pattern dictionary + */ + + // If beginWord equals endWord, the sequence is just the word itself + if (beginWord === endWord) { + return 1; + } + + // If endWord is not in wordList, no valid transformation exists + if (!wordList.includes(endWord)) { + return 0; + } + + // Convert wordList to set for O(1) lookup + const wordSet = new Set(wordList); + + // Add beginWord to the set if not present + if (!wordSet.has(beginWord)) { + wordSet.add(beginWord); + } + + // Build a pattern dictionary to find all words that differ by one letter + // e.g., "hot" -> {"*ot": ["hot"], "h*t": ["hot"], "ho*": ["hot"]} + const patternDict = new Map(); + const wordLen = beginWord.length; + + // Create patterns for all words + for (const word of wordSet) { + for (let i = 0; i < wordLen; i++) { + const pattern = word.slice(0, i) + '*' + word.slice(i + 1); + if (!patternDict.has(pattern)) { + patternDict.set(pattern, []); + } + patternDict.get(pattern)!.push(word); + } + } + + // BFS to find shortest path + const queue: [string, number][] = [[beginWord, 1]]; // [current_word, level] + const visited = new Set([beginWord]); + + while (queue.length > 0) { + const [currentWord, level] = queue.shift()!; + + // Try all possible transformations by replacing each character + for (let i = 0; i < wordLen; i++) { + const pattern = currentWord.slice(0, i) + '*' + currentWord.slice(i + 1); + + // Get all words matching this pattern + const neighbors = patternDict.get(pattern) || []; + for (const nextWord of neighbors) { + if (nextWord === endWord) { + return level + 1; + } + + if (!visited.has(nextWord)) { + visited.add(nextWord); + queue.push([nextWord, level + 1]); + } + } + + // Clear the pattern to avoid revisiting in future iterations + patternDict.set(pattern, []); + } + } + + return 0; +} + diff --git a/tests/test_150_questions_round_22/test_92_word_ladder_round_22.py b/tests/test_150_questions_round_22/test_92_word_ladder_round_22.py new file mode 100644 index 00000000..2b86e98a --- /dev/null +++ b/tests/test_150_questions_round_22/test_92_word_ladder_round_22.py @@ -0,0 +1,79 @@ +import pytest +from src.my_project.interviews.top_150_questions_round_22.ex_92_word_ladder import Solution + + +class TestWordLadder: + def setup_method(self): + self.solution = Solution() + + def test_example_1(self): + """Test Example 1: Standard transformation sequence""" + beginWord = "hit" + endWord = "cog" + wordList = ["hot", "dot", "dog", "lot", "log", "cog"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 5, "Should return 5 for the sequence: hit -> hot -> dot -> dog -> cog" + + def test_example_2(self): + """Test Example 2: endWord not in wordList""" + beginWord = "hit" + endWord = "cog" + wordList = ["hot", "dot", "dog", "lot", "log"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 0, "Should return 0 when endWord is not in wordList" + + def test_single_transformation(self): + """Test single transformation""" + beginWord = "hot" + endWord = "dot" + wordList = ["hot", "dot"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 2, "Should return 2 for direct transformation" + + def test_no_transformation_needed(self): + """Test when begin and end are same""" + beginWord = "hot" + endWord = "hot" + wordList = ["hot"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 1, "Should return 1 when beginWord equals endWord" + + def test_no_path_exists(self): + """Test when no valid path exists""" + beginWord = "hit" + endWord = "cog" + wordList = ["hot", "dot", "tog"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 0, "Should return 0 when no valid transformation sequence exists" + + def test_longer_words(self): + """Test with longer words""" + beginWord = "teach" + endWord = "place" + wordList = ["teach", "peach", "peace", "place", "reach"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 4, "Should return 4 for: teach -> peach -> peace -> place" + + def test_multiple_paths(self): + """Test when multiple paths exist""" + beginWord = "red" + endWord = "tax" + wordList = ["ted", "tex", "red", "tax", "tad", "rex"] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 4, "Should return 4 for shortest path: red -> ted -> tex -> tax" + + def test_empty_word_list(self): + """Test with empty wordList""" + beginWord = "hit" + endWord = "cog" + wordList = [] + + result = self.solution.ladderLength(beginWord, endWord, wordList) + assert result == 0, "Should return 0 when wordList is empty"