Problem Challenge 2
Dry-run templates
This is the implementation of the solution provided for the problem posed in Problem Challenge 2 lesson:
from __future__ import print_functionclass Node:def __init__(self, value, next=None):self.value = valueself.next = nextdef print_list(self):temp = selfwhile temp is not None:print(temp.value, end=" ")temp = temp.nextprint()def rotate(head, rotations):if head is None or head.next is None or rotations <= 0:return head# find the length and the last node of the listlast_node = headlist_length = 1while last_node.next is not None:last_node = last_node.nextlist_length += 1last_node.next = head # connect the last node with the head to make it a circular listrotations %= list_length # no need to do rotations more than the length of the listskip_length = list_length - rotationslast_node_of_rotated_list = headfor i in range(skip_length - 1):last_node_of_rotated_list = last_node_of_rotated_list.next# 'last_node_of_rotated_list.next' is pointing to the sub-list of 'k' ending nodeshead = last_node_of_rotated_list.nextlast_node_of_rotated_list.next = Nonereturn headdef main():head = Node(1)head.next = Node(2)head.next.next = Node(3)head.next.next.next = Node(4)head.next.next.next.next = Node(5)head.next.next.next.next.next = Node(6)print("Nodes of original LinkedList are: ", end='')head.print_list()result = rotate(head, 3)print("Nodes of rotated LinkedList are: ", end='')result.print_list()main()
Students may be encouraged to run through the provided solution with the following sample inputs:
Sample Input #1
Linked List: 11 --> 22 --> 33 --> 44 --> 55 --> 66 --> null
k: 3
Iteration No. | Line no. | head | last_node | list_length | rotations | skip_length | last_node_of_rotated_list |
- | 22-23 | 11 | 11 | 1 | 3 | - | - |
1 | 24-26 | 11 | 22 | 2 | 3 | - | - |
2 | 24-26 | 11 | 33 | 3 | 3 | - | - |
3 | 24-26 | 11 | 44 | 4 | 3 | - | - |
4 | 24-26 | 11 | 55 | 5 | 3 | - | - |
5 | 24-26 | 11 | 66 | 6 | 3 | - | - |
- | 29-31 | 11 | 66 | 6 | 3 | 3 | 11 |
1 | 32-33 | 11 | 66 | 6 | 3 | 3 | 22 |
2 | 32-33 | 11 | 66 | 6 | 3 | 3 | 33 |
3 | 32-33 | 11 | 66 | 6 | 3 | 3 | 44 |
- | 36-37 | 55 | 66 | 6 | 3 | 3 | 44 |
... | ... | ... | ... | ... | ... | ... | ... |
... | ... | ... | ... | ... | ... | ... | ... |
Sample Input #2
Linked List: 3 --> 5 --> 7 --> 9 --> null
k: 8
Iteration No. | Line no. | head | last_node | list_length | rotations | skip_length | last_node_of_rotated_list |
- | 22-23 | 3 | 3 | 1 | 8 | - | - |
1 | 24-26 | 3 | 5 | 2 | 8 | - | - |
2 | 24-26 | 3 | 7 | 3 | 8 | - | - |
3 | 24-26 | 3 | 9 | 4 | 8 | - | - |
- | 29-31 | 3 | 9 | 4 | 0 | 4 | 3 |
1 | 32-33 | 3 | 9 | 4 | 0 | 4 | 5 |
2 | 32-33 | 3 | 9 | 4 | 0 | 4 | 7 |
3 | 32-33 | 3 | 9 | 4 | 0 | 4 | 9 |
- | 36-37 | 3 | 9 | 4 | 0 | 4 | 9 |
... | ... | ... | ... | ... | ... | ... | ... |
... | ... | ... | ... | ... | ... | ... | ... |
Step-by-step solution construction
We need to rotate the linked list by length of the linked list % rotations. Hence, as a first step, we need to traverse the list and calculate the length. In the following code, we are traversing the list on lines 22-31 and incrementing list_length
in each iteration.
from __future__ import print_functionclass Node:def __init__(self, value, next=None):self.value = valueself.next = nextdef print_list(self):temp = selfwhile temp is not None:print(temp.value, end=" ")temp = temp.nextprint()def rotate(head, rotations):if head is None or head.next is None or rotations <= 0:return head# find the length and the last node of the listlast_node = headlist_length = 1iteration = 0print("Calculating list length:")while last_node.next is not None:print("iteration: "+ str(iteration))print("\tlast_node: " + str(last_node.value))print("\tlist_length: " + str(list_length))last_node = last_node.nextlist_length += 1iteration += 1print("LinkedList Length: " + str(list_length))return headdef main():head = Node(11)head.next = Node(22)head.next.next = Node(33)head.next.next.next = Node(44)head.next.next.next.next = Node(55)head.next.next.next.next.next = Node(66)print("Nodes of original LinkedList are: ", end='')head.print_list()result = rotate(head, 8)print("Nodes of rotated LinkedList are: ", end='')result.print_list()main()
In the code below, we are performing the following steps:
- On line 34, we are connecting the last node of the linked list to the first node (head).
Note: In this step, we cannot call the
print_list
method from themain
function as the list has become circular and the method will never terminate.
-
On line 35, we calculate the required number of rotations by taking the modulus with the size of the list computed in the previous step.
-
On line 36, we calculate the required number of nodes to skip to perform the rotation of the nodes from the end of the list.
from __future__ import print_functionclass Node:def __init__(self, value, next=None):self.value = valueself.next = nextdef print_list(self):temp = selfwhile temp is not None:print(temp.value, end=" ")temp = temp.nextprint()def rotate(head, rotations):if head is None or head.next is None or rotations <= 0:return head# find the length and the last node of the listlast_node = headlist_length = 1iteration = 0print("Calculating list length:")while last_node.next is not None:print("iteration: "+ str(iteration))print("\tlast_node: " + str(last_node.value))print("\tlist_length: " + str(list_length))last_node = last_node.nextlist_length += 1iteration += 1print("LinkedList Length: " + str(list_length))last_node.next = head # connect the last node with the head to make it a circular listrotations %= list_length # no need to do rotations more than the length of the listskip_length = list_length - rotations # no. of nodes to skip to rotate the elements at the end of the listlast_node_of_rotated_list = headprint("Rotations: "+str(rotations))print("skip_length: "+str(skip_length))print("last_node_of_rotated_list: "+str(last_node_of_rotated_list.value))print("head: "+str(head.value))return headdef main():head = Node(11)head.next = Node(22)head.next.next = Node(33)head.next.next.next = Node(44)head.next.next.next.next = Node(55)head.next.next.next.next.next = Node(66)print("Nodes of original LinkedList are: ", end='')head.print_list()result = rotate(head, 8)#print("Nodes of rotated LinkedList are: ", end='')#result.print_list()main()
Until now, we have set up the following:
skip_length
: the number of nodes to skip from the left- Made the list circular: connected the last node of the list to the head
We need to write code to skip skip_length
nodes from the head
(lines 44-45), set head
to point to the front of the list (line 51) and set the last skipped node’s next
to None
(line 52) .
from __future__ import print_functionclass Node:def __init__(self, value, next=None):self.value = valueself.next = nextdef print_list(self):temp = selfwhile temp is not None:print(temp.value, end=" ")temp = temp.nextprint()def rotate(head, rotations):if head is None or head.next is None or rotations <= 0:return head# find the length and the last node of the listlast_node = headlist_length = 1iteration = 0print("Calculating list length:")while last_node.next is not None:print("iteration: "+ str(iteration))print("\tlast_node: " + str(last_node.value))print("\tlist_length: " + str(list_length))last_node = last_node.nextlist_length += 1iteration += 1print("LinkedList Length: " + str(list_length))last_node.next = head # connect the last node with the head to make it a circular listrotations %= list_length # no need to do rotations more than the length of the listskip_length = list_length - rotationslast_node_of_rotated_list = headprint("Rotations: "+str(rotations))print("skip_length: "+str(skip_length))print("last_node_of_rotated_list: "+str(last_node_of_rotated_list.value))iteration = 0for i in range(skip_length - 1):last_node_of_rotated_list = last_node_of_rotated_list.nextprint("iteration: "+ str(iteration))print("last_node_of_rotated_list: "+str(last_node_of_rotated_list.value))iteration += 1# 'last_node_of_rotated_list.next' is pointing to the sub-list of 'k' ending nodeshead = last_node_of_rotated_list.nextlast_node_of_rotated_list.next = Noneprint("head: "+str(head.value))return headdef main():head = Node(11)head.next = Node(22)head.next.next = Node(33)head.next.next.next = Node(44)head.next.next.next.next = Node(55)head.next.next.next.next.next = Node(66)print("Nodes of original LinkedList are: ", end='')head.print_list()result = rotate(head, 8)print("Nodes of rotated LinkedList are: ", end='')result.print_list()main()