From 54a28af8a752f2cccca32071a5d4add741838c53 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 24 Jan 2026 04:28:26 -0600 Subject: [PATCH] adding algo --- .../ex_58_copy_list_with_random_pointer.py | 39 ++++++ .../top_150_questions_round_1/Node.ts | 12 ++ .../ex_58_copy_list_with_random_pointer.ts | 40 ++++++ ..._copy_list_with_random_pointer_round_22.py | 120 ++++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 src/my_project/interviews/top_150_questions_round_22/ex_58_copy_list_with_random_pointer.py create mode 100644 src/my_project/interviews_typescript/top_150_questions_round_1/Node.ts create mode 100644 src/my_project/interviews_typescript/top_150_questions_round_1/ex_58_copy_list_with_random_pointer.ts create mode 100644 tests/test_150_questions_round_22/test_58_copy_list_with_random_pointer_round_22.py diff --git a/src/my_project/interviews/top_150_questions_round_22/ex_58_copy_list_with_random_pointer.py b/src/my_project/interviews/top_150_questions_round_22/ex_58_copy_list_with_random_pointer.py new file mode 100644 index 00000000..bd4b176e --- /dev/null +++ b/src/my_project/interviews/top_150_questions_round_22/ex_58_copy_list_with_random_pointer.py @@ -0,0 +1,39 @@ +from typing import List, Union, Collection, Mapping, Optional +from abc import ABC, abstractmethod + +# Definition for a Node. +class Node: + def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None): + self.val = int(x) + self.next = next + self.random = random + +class Solution: + def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]': + """ + Approach 1: Using HashMap + Time Complexity: O(n) + Space Complexity: O(n) + """ + if not head: + return None + + # Map old nodes to new nodes + old_to_new = {} + + # First pass: create all new nodes + curr = head + while curr: + old_to_new[curr] = Node(curr.val) + curr = curr.next + + # Second pass: assign next and random pointers + curr = head + while curr: + if curr.next: + old_to_new[curr].next = old_to_new[curr.next] + if curr.random: + old_to_new[curr].random = old_to_new[curr.random] + curr = curr.next + + return old_to_new[head] diff --git a/src/my_project/interviews_typescript/top_150_questions_round_1/Node.ts b/src/my_project/interviews_typescript/top_150_questions_round_1/Node.ts new file mode 100644 index 00000000..1a281a48 --- /dev/null +++ b/src/my_project/interviews_typescript/top_150_questions_round_1/Node.ts @@ -0,0 +1,12 @@ +// Definition for a Node. +export class _Node { + val: number; + next: _Node | null; + random: _Node | null; + + constructor(val?: number, next?: _Node | null, random?: _Node | null) { + this.val = val ?? 0; + this.next = next ?? null; + this.random = random ?? null; + } +} \ No newline at end of file diff --git a/src/my_project/interviews_typescript/top_150_questions_round_1/ex_58_copy_list_with_random_pointer.ts b/src/my_project/interviews_typescript/top_150_questions_round_1/ex_58_copy_list_with_random_pointer.ts new file mode 100644 index 00000000..32410776 --- /dev/null +++ b/src/my_project/interviews_typescript/top_150_questions_round_1/ex_58_copy_list_with_random_pointer.ts @@ -0,0 +1,40 @@ +import { _Node } from "./Node"; + +function copyRandomList(head: _Node | null): _Node | null { + /** + * Approach: Using HashMap + * Time Complexity: O(n) + * Space Complexity: O(n) + */ + if (head === null) { + return null; + } + + // Map old nodes to new nodes + const oldToNew = new Map<_Node, _Node>(); + + // First pass: create all new nodes + let curr: _Node | null = head; + while (curr !== null) { + oldToNew.set(curr, new _Node(curr.val)); + curr = curr.next; + } + + // Second pass: assign next and random pointers + curr = head; + while (curr !== null) { + const newNode = oldToNew.get(curr)!; + + if (curr.next !== null) { + newNode.next = oldToNew.get(curr.next)!; + } + + if (curr.random !== null) { + newNode.random = oldToNew.get(curr.random)!; + } + + curr = curr.next; + } + + return oldToNew.get(head)!; +} diff --git a/tests/test_150_questions_round_22/test_58_copy_list_with_random_pointer_round_22.py b/tests/test_150_questions_round_22/test_58_copy_list_with_random_pointer_round_22.py new file mode 100644 index 00000000..fff556c1 --- /dev/null +++ b/tests/test_150_questions_round_22/test_58_copy_list_with_random_pointer_round_22.py @@ -0,0 +1,120 @@ +import unittest +from src.my_project.interviews.top_150_questions_round_22\ +.ex_58_copy_list_with_random_pointer import Solution, Node + +class CopyListWithRandomPointerTestCase(unittest.TestCase): + + def create_linked_list_with_random(self, values): + """ + Helper function to create a linked list with random pointers. + + :param values: List of [val, random_index] pairs + :return: Head of the linked list + """ + if not values: + return None + + # Create all nodes first + nodes = [] + for val, _ in values: + nodes.append(Node(val)) + + # Connect next pointers and random pointers + for i in range(len(nodes)): + if i < len(nodes) - 1: + nodes[i].next = nodes[i + 1] + + random_index = values[i][1] + if random_index is not None: + nodes[i].random = nodes[random_index] + + return nodes[0] + + def linked_list_to_list(self, head): + """ + Helper function to convert linked list with random pointers to list format. + + :param head: Head of the linked list + :return: List of [val, random_index] pairs + """ + if not head: + return [] + + # Create a map of nodes to their indices + node_to_index = {} + curr = head + index = 0 + while curr: + node_to_index[curr] = index + curr = curr.next + index += 1 + + # Build the result + result = [] + curr = head + while curr: + random_index = node_to_index.get(curr.random) if curr.random else None + result.append([curr.val, random_index]) + curr = curr.next + + return result + + def test_example_1(self): + # Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] + # Output: [[7,null],[13,0],[11,4],[10,2],[1,0]] + solution = Solution() + head = self.create_linked_list_with_random([[7, None], [13, 0], [11, 4], [10, 2], [1, 0]]) + copied_head = solution.copyRandomList(head) + result = self.linked_list_to_list(copied_head) + target = [[7, None], [13, 0], [11, 4], [10, 2], [1, 0]] + self.assertEqual(result, target) + + # Verify deep copy - nodes should be different objects + self.assertIsNot(head, copied_head) + + def test_example_2(self): + # Input: head = [[1,1],[2,1]] + # Output: [[1,1],[2,1]] + solution = Solution() + head = self.create_linked_list_with_random([[1, 1], [2, 1]]) + copied_head = solution.copyRandomList(head) + result = self.linked_list_to_list(copied_head) + target = [[1, 1], [2, 1]] + self.assertEqual(result, target) + + # Verify deep copy + self.assertIsNot(head, copied_head) + + def test_example_3(self): + # Input: head = [[3,null],[3,0],[3,null]] + # Output: [[3,null],[3,0],[3,null]] + solution = Solution() + head = self.create_linked_list_with_random([[3, None], [3, 0], [3, None]]) + copied_head = solution.copyRandomList(head) + result = self.linked_list_to_list(copied_head) + target = [[3, None], [3, 0], [3, None]] + self.assertEqual(result, target) + + # Verify deep copy + self.assertIsNot(head, copied_head) + + def test_empty_list(self): + # Input: head = [] + # Output: [] + solution = Solution() + head = None + copied_head = solution.copyRandomList(head) + self.assertIsNone(copied_head) + + def test_single_node(self): + # Input: head = [[1,null]] + # Output: [[1,null]] + solution = Solution() + head = self.create_linked_list_with_random([[1, None]]) + copied_head = solution.copyRandomList(head) + result = self.linked_list_to_list(copied_head) + target = [[1, None]] + self.assertEqual(result, target) + + # Verify deep copy + self.assertIsNot(head, copied_head) \ No newline at end of file