Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions datastructures/linked_lists/singly_linked_list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -618,3 +618,68 @@ You don’t need to modify the values in the list’s nodes; only the links betw
![Example 3](./images/examples/singly_linked_list_reorder_list_example_3.png)
![Example 4](./images/examples/singly_linked_list_reorder_list_example_4.png)
![Example 5](./images/examples/singly_linked_list_reorder_list_example_5.png)

---
## Swap Nodes in Pairs

Given a singly linked list, swap every two adjacent nodes of the linked list. After the swap, return the head of the
linked list.

Note: Solve the problem without modifying the values in the list’s nodes. In other words, only the nodes themselves can
be changed.

### Constraints

- The number of nodes in the list is in the range [0,100]
- 0 <= `node.value` <= 100

### Solution

The essence of this solution lies in understanding that we need to swap nodes in pairs without altering the values within
the nodes. To accomplish this, we use an in-place reversal approach, manipulating pointers to rearrange the nodes while
preserving the overall structure of the linked list. By adjusting the pointers of each node, we can efficiently swap the
nodes in place in linear time without needing extra space or altering the data. This method ensures that the linked list
remains intact and correctly ordered, with each pair of nodes swapped seamlessly as we progress through the list.

The algorithm for this problem is as follows:

- Initialize a dummy node that would reference the first node of the linked list, which is the head of the linked list.
We’ll use prev_node to update the pointer of the dummy node.

- Next, we iterate over the linked list and swap the pairs of nodes as we proceed. The two nodes to be swapped can be
represented as first_node and second_node.

These steps are represented in the following illustration:

![Solution 1](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_1.png)
![Solution 2](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_2.png)
![Solution 3](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_3.png)
![Solution 4](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_4.png)
![Solution 5](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_5.png)

- After the swap, update the position of the previous node and the head node for the next swap.
- Reinitialize first_node to prev_node to ensure that the nodes are swapped on the go and attached to the previously
swapped list. Ultimately, we’ll get the final reversed pairs of linked lists.

> Note: Ultimately, we have to return the second node because, at the end of the final iteration, the second node of the
> list would have technically become the first node of the list.
> The reference of the first node is secured by the previous node in the first swap when we assign prev_node = first_node.

The following illustration shows these steps in detail:

![Solution 6](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_6.png)
![Solution 7](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_7.png)
![Solution 8](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_8.png)
![Solution 9](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_9.png)
![Solution 10](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_10.png)
![Solution 11](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_11.png)
![Solution 12](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_12.png)
![Solution 13](./images/solutions/singly_linked_list_swap_nodes_in_pairs_solution_13.png)

#### Time Complexity

The time complexity of the solution above is O(n), where n is the number of nodes in the linked list.

#### Space Complexity

The space complexity of the solution above is O(1).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ def is_palindrome_2(self) -> bool:

return True

def pairwise_swap(self) -> Optional[SingleNode]:
def pairwise_swap_with_modification(self) -> Optional[SingleNode]:
"""
Swaps nodes in pairs.
However, this swaps the values of the nodes in pairs and not the pointers
Expand Down Expand Up @@ -754,7 +754,7 @@ def pairwise_swap(self) -> Optional[SingleNode]:
# at this point, the linked list has been swapped in pairs
return self.head

def pairwise_swap_two(self) -> Optional[SingleNode]:
def pairwise_swap(self) -> Optional[SingleNode]:
"""
Swaps nodes in pairs without swapping the values in the nodes.

Expand All @@ -765,20 +765,32 @@ def pairwise_swap_two(self) -> Optional[SingleNode]:
if not self.head:
return self.head

start = SingleNode(None)
start.next = self.head
self.head = start

while self.head.next and self.head.next.next:
temp = self.head.next.next

self.head.next.next = temp.next
temp.next = self.head.next

self.head.next = temp
self.head = self.head.next.next

return start.next
# Create a dummy node with a value of None
dummy_node = SingleNode(None)
# This dummy node acts as the prev_node for the head node
# of the list and hence stores pointer to the head node
dummy_node.next = self.head
prev_node = dummy_node

# While the head node and the next node exist
while self.head and self.head.next:
# nodes to be swapped
first_node = self.head
second_node = self.head.next

# perform swapping of nodes
# i. Set the previous node's next node to be the second node
prev_node.next = second_node
# ii. Set the first node's next node to be the second node's next node
first_node.next = second_node.next
# iii. Set the second node's next node to be the first node
second_node.next = first_node

# re-initialise the head and the previous node for next swap
prev_node = first_node
self.head = first_node.next

return dummy_node.next

def swap_nodes_at_kth_and_k_plus_1(self, k: int) -> SingleNode:
a, b = self.head, self.head
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ def test_two(self):
linked_list.append(3)
linked_list.append(4)

head = linked_list.pairwise_swap_two()
actual = linked_list.pairwise_swap()

expected_head = SingleNode(
2, next_=SingleNode(1, next_=SingleNode(4, next_=SingleNode(3)))
)

self.assertEqual(head, expected_head)
self.assertEqual(expected_head, actual)

def test_three(self):
"""7 -> 2 -> 1 should become 2 -> 7 -> 1"""
Expand All @@ -32,11 +32,11 @@ def test_three(self):
linked_list.append(2)
linked_list.append(1)

head = linked_list.pairwise_swap_two()
actual = linked_list.pairwise_swap()

expected_head = SingleNode(2, next_=SingleNode(7, next_=SingleNode(1)))

self.assertEqual(head, expected_head)
self.assertEqual(expected_head, actual)


if __name__ == "__main__":
Expand Down
Loading