Iterative solution to reverse linked list in sets of k - python

Given a singly linked list, i am trying to reverse k nodes at a time through out the list.
So, if k = 2, 1 -> 2 -> 3 -> 4 -> 5 -> 6 will turn into 2 -> 1 -> 4 -> 3 -> 6 -> 5. It is assumed that k is always a factor of the length of the list (Length of the list is divisible by k).
I am trying to solve this using an iterative approach rather than a recursive one. I am trying to parse the list as sets of k nodes and reverse them each till the end of the list. This is my code
def reverseList(A, B): # param A : head node of linked list, param B : integer, return the head node in the list
if B < 2:
return A
dummy = ListNode('dummy')
dummy.next = A
prev, behind = dummy, A
while behind:
ahead = behind
for i in range(B-1):
ahead = ahead.next
new_behind = reverse_list(behind, ahead)
prev.next = ahead
behind.next = new_behind
behind = behind.next
return dummy.next
The reverse_list function reverses the list from the start to end nodes of a k set and returns the node at the beginning of the new k set of nodes (the new start node)
def reverse_list(start, end):
prev, curr = None, start
while prev is not end:
next = curr.next
curr.next = prev
prev = curr
curr = next
return curr
The definition of ListNode class
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
When the values A = [ 6 -> 10 -> 0 -> 3 -> 4 -> 8 ] and B = 3 are given, the output is 8 -> 4 -> 3. What exactly am I missing or overlooking? Any help is greatly appreciated.

For each iteration, you should point the next node of the current node to the next node of the next node, then point the next node of the next node to the head node, and then point the head node to the next node, to complete a reversal of the give number of nodes. Then assign the current node as the new head, repeat the above, until the next node of the head is None:
def reverseList(A, B):
head = A
while head.next:
node = head.next
for _ in range(B - 1):
next_node = node.next
if next_node:
node.next = next_node.next
next_node.next = head.next
head.next = next_node
head = node
return A
Demo: https://repl.it/#blhsing/ElatedSurefootedFilesize

I've figured out the mistake i've been making. I didn't update the 'prev' pointer while updating the 'behind' pointer. It should have been
prev = behind
After getting the behind and ahead pointers, this should be the block of code within the while loop in reverseList function
new_behind = reverse_list(behind, ahead)
prev.next = ahead
behind.next = new_behind
prev = behind
behind = behind.next

Related

What is wrong in my code...Remove duplicates from an unsorted linked list

Remove duplicates from an unsorted linked list
Given an unsorted linked list of N nodes. The task is to remove duplicate elements from this unsorted Linked List. When a value appears in multiple nodes, the node which appeared first should be kept, all others duplicates are to be removed.
Example 1:
Input:
N = 4
value[ ] = {5,2,2,4}
Output: 5 2 4
Example 2:
Input:
N = 5
value[] = {2,2,2,2,2}
Output: 2
My Code
def removeDuplicates(head):
if head is None or not head.next:
return head
d = {}
curr = head
prev = None
while curr.next:
prev = curr
curr = curr.next
if curr.data in d:
prev.next = curr.next
else:
d[curr.data] = 1
return head
In your while loop as condition you need curr instead of curr.next. And you need to overwrite curr at the end of the while loop. Like this:
def removeDuplicates(head):
if head is None or not head.next:
return head
d = {}
curr = head
prev = None
while curr:
if curr.data in d:
prev.next = curr.next
else:
d[curr.data] = 1
prev = curr
curr = curr.next
return head

how do I skip a middle node?

I am trying to write code for a Linked List so that it deletes a node in the linked list, it can be any node except for the first and last nodes in the linked list. I have come up with some ideas below.
I'm not sure how to complete it, I know there needs to be some reference to k in the while loop, so that we skip over the node when traversing the linked list, but how can I reference this k? Would I do a 'for I in range k', and then on the kth iteration perform the skip?
def delete_middle(l1,k):
if l1.head is None:
return None
current = l1.head
while current:
if current == k:
current.next = current.next.next
current = current.next
return head
node.value = node.next.value
node.next = node.next.next
If you want to remove the kth node where k is an integer you can do this:
def delete_middle(l1,k):
if (l1.head is None) or (k == 0) or (k == find_length(l1) - 1): # second condition checks if k is the first value and the third condition checks if k is the last value which you didn't want to remove.
return None
n = 0 # index counter for the values in the linked list
head = l1.head
current = head
while current is not None:
if n + 1 == k: # check if the next node is the node that you want to remove
current.next = current.next.next
break
current = current.next
n += 1
return head
def find_length(l1): # to returns the length of the linked list
curr = l1.head
n = 0
while curr is not None:
curr = curr.next
n += 1
return n
Also, I'd recommend defining a linked list class with methods like these inside so you won't have to care about returning any value while updating the linked list unless an invalid value is sent.

What is the reason for Time Limit exceeded here

Given a linked list, rotate the list to the right by k places, where k is non-negative.
Here are some examples:
Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL
Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL
Code:
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if k < 0:
return head
if head is None or head.next is None:
return head
it = head
while k != 0:
while it.next.next is not None:
it = it.next
temp = it.next
it.next = None
temp.next = head
head = temp
it = head
k -= 1
return head
The above code is working fine for k < 2000000.
The test case that is failing is -
Last executed input:
[1,2,3]
2000000000
Error: Time Limit Exceeded
The time complexity will be O(k* length of the list), correct?

Count Linked List Nodes

I am trying to count the numbers of nodes in a linked list when the node value is a non-negative odd, but it seems that I couldn't get the right result.
class Solution:
"""
#param head:
#return: nothing
"""
def countNodesII(self, head):
count = 0
while head.next is not None:
head = head.next
if head.val > 0 and head.val % 2 != 0:
count += 1
else:
return 0
return count
if the input is 1->3->5->null
I expect to get result of 3, but my program returned 2 instead.
Some issues in your code
You would want to move to next node via head=head.next after you check the head node for the condition, right now you are skipping head
You would want to remove return from else, and only return count at the end
You want to check if head reaches None since you are using it to iterate over your list
So the updated code will look like
class Solution:
"""
#param head:
#return: nothing
"""
def countNodesII(self, head):
count = 0
#Iterate over the list
while head != None:
#Check for condition
if head.val > 0 and head.val % 2 != 0:
count += 1
#Move to next node
head = head.next
return count

Set list next to None

When I try to make the next attribute of a node, p, of a linked list point to None, I use p.next = None. But what if I want to make the node corresponding to p.next to None?
An example would be when try to rotate a linked list, which ends with a node's next equal to None, I want to make the new list's last element's next point to None but I think I keep deleting the element that it pointed to.
Here's my code for rotating the list by k positions. If you want to see the full description of the problem see here
def rotate(head, k):
'''
head is pointer to the head, k is the number of positions to rotate
'''
if not head or k == 0:
return head
p = head
d = head
counter = 1
while p.next != None:
counter += 1
p = p.next
out = ListNode(0)
if k % counter == 0:
return head
if counter < k:
counter = counter % k
for _ in range(counter):
p.next = d
d = d.next
p = p.next
out = p
d.next.next = None
return out
Sounds like you want to take the last k values and append them to the front.
p.next is the next node. In general when we want to change p's next we need to grab temp = p.next p.next = newNode and then we can continue.
In this case though, I'd find the length of the list, set tail.next = head, subtract k (accounting for wraparound), then walk forward till N-k, and set that node's p.next = None
Something like:
p, len, prev = head, 0, None
while p:
prev = p
p = p.next
len += 1
# prev is tail, set it's next to head
prev.next = head
# find the node to detach
p = head
for i in xrange(len):
p = p.next
p.next = None
You'll need to figure out corner cases

Categories