简体   繁体   中英

Find kth to last element of a singly Linked List recursively -Python

I am new to Python and am practicing simple data structures in the process of learning python.I tried implementing the problem to find kth to last element in python using recursion:

This is my code:

def kthtoLast(self,head,k,i):  #recursion
    if(head==None):
        return 0

    i= kthtoLast(self,head.next,k) + 1
    if(i==k):
        print(head.node)
    return i

but I am getting an error -

NameError: name 'kthtoLast' is not defined.

Though I have defined the function and am calling it after creating object of my class -

l=LinkedList()
l.kthtoLast(l.head,3,0)

Can anyone please help me in understanding where am I going wrong?

The complete code looks like:

class Node(object):
    def __init__(self,node,next=None):
        self.node=node
        self.next=next
class LinkedList(object):
    def __init__(self,head=None):
        self.head=head
    def append(self,data):
        new_node=Node(data,self.head)
        self.head=new_node
    def kLast(self,current,k):  #recursion
        if(current.next==None):
            return 0
        i= kLast(self,current.next,k) + 1
        if(i==k):
            print(current.node)
        return i
l=LinkedList()
l.append(12)
l.append(45)
l.append(7988)
l.append(89)
l.append(74)
print(l.head)
l.kLast(l.head,3)

当您从同一个类的另一个实例方法调用类的实例方法时,您应该使用self.<method>() ,因此在您的情况下,调用变为 -

i = self.kthtoLast(head.next,k) + 1

As an alternative option you could use two pointer solution which is little more efficient in terms of complexity.

Here how it works:

The solution is have two pointers….(fast and slow). We keep incrementing/moving the fast pointer first (while NOT moving/incrementing slow pointer). This way, the fast pointer would move by nth count to next node then we move/increment slow pointer too. Once fast pointer reaches the end then we know the slow pointer is at nth node from the last.

Some additional information: second to last means next to and 1 to last it means the last node itself !

               pointer
               to next
  +----------+ node     +----------+          +----------+
  | Data  |  +--------> | Data  |  +--------> | Data  |  |
  +----------+          +----------+          +----------+

     ^                                            ^
     |                                            |
     |                                            |
  +-------+                                    +-------+
  |slow   |                                    |fast   |
  |pointer|                                    |pointer|
  +-------+                                    +-------+
  keep moving the fast pointer to the end

  +------------------------------------------------------>

  but only move the slow pointer forward when fast pointer has passed n nodes

  +------->

here is the code:

class Node: 
    def __init__(self, data): 
        self.data = data 
        self.next = None

class LinkedList:  
    def __init__(self): 
        self.head = None

    def append(self, value):
        if not self.head:
            self.head = Node(value)
        else:
            temp = self.head
            # go to the last one 
            while temp.next:
                temp = temp.next
            # now we are just adding a new to the end of the linkedlist    
            temp.next = Node(value)

    # the main logic
    def print_nth_from_last(self, n): 
        slow_pointer = self.head 
        fast_pointer = self.head  


        counter = 1
        while(fast_pointer  is not None): 
            fast_pointer  = fast_pointer.next 
            # don't allow slower pointer to go to next node until the faster pointer has moved by nth value. 
            # in other words, hold slower_point behind nth value! 
            if counter > n: 
                slow_pointer = slow_pointer.next 
            counter +=1
        if n >= counter:
            print("error - nth value is greater than number of nodes you have ")
        else:   
            print (n,"elements from last is:" , slow_pointer.data)


#let's populate the linkedlist
linkedList = LinkedList() 
linkedList.append(20)
linkedList.append(4)
linkedList.append(15)
linkedList.append(35)

#note you can pass zero 
linkedList.print_nth_from_last(3) 

Given that you have ListNode:

class ListNode:
def __init__(self, data=0, next=None):
    self.data = data
    self.next = next

You can do something like:

def find_n_to_last(node, n):
    """Returns nth to last element from the linked list."""
    def find_n_to_last_helper(node, n, count):
        if not node:
            return None

        result = find_n_to_last_helper(node.next, n, count)
        if count[0] == n:
            result = node.data

        count[0] += 1 
        return result 

    count = [0]
    return find_n_to_last_helper(node, n, count)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM