forked from UTSAVS26/PyVerse
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
UTSAVS26#881 added clone linked list
Clone a linked list where each node has a next pointer and a random pointer that can reference any node or be None.
- Loading branch information
Showing
2 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
Algorithms_and_Data_Structures/Linked List/Clone_a_List_with_Random_Pointers/program.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
class ListNode: | ||
def __init__(self, x): | ||
self.val = x | ||
self.next = None | ||
self.random = None | ||
|
||
# Function to clone the linked list with random pointers | ||
def clone_linked_list_with_random_pointer(head): | ||
if not head: | ||
return None | ||
|
||
# Step 1: Create a dictionary to store the mapping from original to cloned nodes | ||
node_map = {} | ||
|
||
# Step 2: First pass to create all nodes (without setting next or random) | ||
curr = head | ||
while curr: | ||
node_map[curr] = ListNode(curr.val) # Map original node to its clone | ||
curr = curr.next | ||
|
||
# Step 3: Second pass to set next and random pointers | ||
curr = head | ||
while curr: | ||
node_map[curr].next = node_map.get(curr.next) # Set the next pointer | ||
node_map[curr].random = node_map.get(curr.random) # Set the random pointer | ||
curr = curr.next | ||
|
||
# Return the head of the cloned list | ||
return node_map[head] | ||
|
||
# Helper function to create a linked list from a list of values and random indices | ||
def create_linked_list(values, random_indices): | ||
if not values: | ||
return None | ||
|
||
# Create all nodes | ||
nodes = [ListNode(val) for val in values] | ||
|
||
# Set the next pointers | ||
for i in range(len(nodes) - 1): | ||
nodes[i].next = nodes[i + 1] | ||
|
||
# Set the random pointers based on random_indices | ||
for i, random_index in enumerate(random_indices): | ||
if random_index != -1: # -1 indicates no random pointer | ||
nodes[i].random = nodes[random_index] | ||
|
||
return nodes[0] | ||
|
||
# Helper function to print the linked list along with random pointers | ||
def print_linked_list(head): | ||
curr = head | ||
while curr: | ||
random_val = curr.random.val if curr.random else "NULL" | ||
print(f"Node({curr.val}) -> Random({random_val})") | ||
curr = curr.next | ||
|
||
# Main function to demonstrate cloning | ||
if __name__ == "__main__": | ||
# Define values and random indices for each node | ||
values = [1, 2, 3, 4, 5] | ||
random_indices = [2, 4, -1, 0, 1] # -1 indicates no random pointer | ||
|
||
# Create the linked list with random pointers | ||
original_list = create_linked_list(values, random_indices) | ||
|
||
print("Original list with random pointers:") | ||
print_linked_list(original_list) | ||
|
||
# Clone the linked list | ||
cloned_list = clone_linked_list_with_random_pointer(original_list) | ||
|
||
print("\nCloned list with random pointers:") | ||
print_linked_list(cloned_list) |
57 changes: 57 additions & 0 deletions
57
...hms_and_Data_Structures/Linked List/Clone_a_List_with_Random_Pointers/readme.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Clone a Linked List with Random Pointers | ||
|
||
## Problem Statement | ||
|
||
Given a linked list where each node contains: | ||
- An integer `val`. | ||
- A `next` pointer to the next node in the list. | ||
- A `random` pointer that points to any node in the list or is `NULL`. | ||
|
||
The task is to **create a deep copy (clone) of this linked list**. The cloned list should have the same values, `next`, and `random` pointer connections as the original list but should not share any nodes with it. | ||
|
||
## Example | ||
|
||
Consider a linked list where: | ||
- Node values: `[1, 2, 3, 4, 5]` | ||
- Random pointers map as follows: | ||
- `1`'s random points to `3` | ||
- `2`'s random points to `5` | ||
- `3` has no random pointer (`NULL`) | ||
- `4`'s random points to `1` | ||
- `5`'s random points to `2` | ||
|
||
The structure of both the original and cloned list should look like this: | ||
|
||
Original list: 1 -> 2 -> 3 -> 4 -> 5 | | | ↓ ↓ ↓ 3 5 1 | ||
|
||
Cloned list: 1' -> 2' -> 3' -> 4' -> 5' | | | ↓ ↓ ↓ 3' 5' 1' | ||
|
||
## Solution Approach | ||
|
||
1. **Mapping Original Nodes to Clones**: Use a dictionary to map each node in the original list to its corresponding cloned node, created based on its `val`. | ||
2. **Setting Pointers**: Traverse the list a second time to set the `next` and `random` pointers for each cloned node. | ||
3. **Return Cloned List**: Return the head of the cloned list. | ||
|
||
## Steps to Solve | ||
|
||
### Step 1: Mapping Original Nodes to Clones | ||
- Use a dictionary (`node_map`) to store a mapping of each node in the original list to its clone, initially creating cloned nodes without setting `next` or `random` pointers. | ||
|
||
### Step 2: Setting `next` and `random` Pointers | ||
- Traverse the list again and set the `next` and `random` pointers for each cloned node using the `node_map` dictionary: | ||
- **Next Pointer**: Map each node's `next` pointer to the corresponding clone. | ||
- **Random Pointer**: Map each node's `random` pointer to the corresponding clone. | ||
|
||
### Step 3: Return the Cloned Head | ||
- Return the cloned head node from `node_map`. | ||
|
||
## Code Walkthrough | ||
|
||
1. **`clone_linked_list_with_random_pointer(head)`**: Clones the linked list using a dictionary to map each original node to its clone. | ||
2. **`create_linked_list(values, random_indices)`**: Creates a linked list with given `values` and `random` pointers based on the indices in `random_indices`. | ||
3. **`print_linked_list(head)`**: Helper function to print each node’s value and its `random` pointer, if any. | ||
|
||
|
||
**Explanation of Complexity** | ||
- Time Complexity: 𝑂(𝑛), where n is the number of nodes in the list. We traverse the list twice. | ||
- Space Complexity: 𝑂(𝑛), due to the use of the hash map to store mappings from original to cloned nodes. |