Reverse every k nodes of a linked list

前端 未结 7 996
夕颜
夕颜 2020-12-15 01:42

I am preparing for a technical interview and I am stuck at writing this program to reverse every k nodes of a linked list.

For example

1->2->3         


        
相关标签:
7条回答
  • 2020-12-15 01:57
    public class ReverseEveryKNodes<K>
    {
          private static class Node<K>
          {
            private K k;
            private Node<K> next;
    
            private Node(K k)
            {
                this.k = k;
            }
          }
    private Node<K> head;
    private Node<K> tail;
    private int size;
    
    public void insert(K kk)
    {
        if(head==null)
        {
            head = new Node<K>(kk);
            tail = head;
        }
        else
        {
            tail.next = new Node<K>(kk);
            tail = tail.next;
        }
        size++;
    }
    
    public void print()
    {
        Node<K> temp = head;
        while(temp!=null)
        {
            System.out.print(temp.k+"--->");
            temp = temp.next;
        }
        System.out.println("");
    }
    
    public void reverse(int k)
    {
        head = reverseK(head, k);
    }
    
    Node<K> reverseK(Node<K> n, int k)
    {
        if(n==null)return null;
    
        Node<K> next=n, c=n, previous=null;
        int count = 0;
        while(c!=null && count<k)
        {
            next=c.next;
            c.next=previous;
            previous=c;
            c=next;
            count++;
        }
        n.next=reverseK(c, k);
        return previous;
    }
    
    public static void main(String[] args)
    {
        ReverseEveryKNodes<Integer> r = new ReverseEveryKNodes<Integer>();
        r.insert(10);
        r.insert(12);
        r.insert(13);
        r.insert(14);
        r.insert(15);
        r.insert(16);
        r.insert(17);
        r.insert(18);
        r.print();
        r.reverse(3);
        r.print();
    }
    }
    
    0 讨论(0)
  • 2020-12-15 02:00

    Yeah, I have never been a fan of recursion, so here is my shot at it using iteration:

      public Node reverse(Node head, int k) {
           Node st = head;
           if(head == null) {
             return null;
           }
    
           Node newHead = reverseList(st, k);
           st = st.next;  
    
           while(st != null) {
             reverseList(st, k);
             st = st.next;
           } 
    
           return newHead
    
      }
    
    
     private Node reverseList(Node head, int k) {
    
          Node prev = null;
          Node curr = head;
          Node next = head.next;
    
          while(next != null && k != 1){
           curr.next = prev;
           prev = curr;
           curr = next;
           next = next.next;
           --k;
          }
          curr.next = prev;
    
          // head is the new tail now.
          head.next = next;
    
          // tail is the new head now.
          return curr;
     }
    
    0 讨论(0)
  • 2020-12-15 02:00

    The following solution uses extra space for storing pointers,and reverses each chunk of list separately. Finally,the new list is built. When I tested, this seemed to cover the boundary conditions.

    template <typename T>
    struct Node {
    T data;  
    struct Node<T>* next;
    Node()  {  next=NULL; } 
    };
    template <class T>
    void advancePointerToNextChunk(struct Node<T> * & ptr,int  & k)  {
    int count =0;  
    while(ptr && count <k )  {
        ptr=ptr->next; 
        count ++; 
    }
    k=count;}
    
    /*K-Reverse Linked List */
    template <class T>  
     void kReverseList( struct Node<T> * & head,  int k){ 
     int storeK=k,numchunk=0,hcount=0;
     queue < struct Node<T> *> headPointerQueue;  
     queue <struct Node<T> *>  tailPointerQueue; 
    
     struct Node<T> * tptr,*hptr;
     struct Node<T> * ptr=head,*curHead=head,*kReversedHead,*kReversedTail;
     while (ptr) {
     advancePointerToNextChunk(ptr,storeK);
     reverseN(curHead,storeK,kReversedHead,kReversedTail);
     numchunk++; 
     storeK=k; 
     curHead=ptr;
     tailPointerQueue.push(kReversedTail),headPointerQueue.push(kReversedHead); 
     }
     while( !headPointerQueue.empty() ||  !tailPointerQueue.empty() )  {
        if(!headPointerQueue.empty()) {
            hcount++;  
            if(hcount == 1) { 
                head=headPointerQueue.front(); 
                headPointerQueue.pop();
            }
            if(!headPointerQueue.empty()) {
            hptr=headPointerQueue.front(); 
            headPointerQueue.pop(); 
            }
        }
        if( !tailPointerQueue.empty() ) {
            tptr=tailPointerQueue.front();  
            tailPointerQueue.pop(); 
        }
        tptr->next=hptr;  
     }
     tptr->next=NULL;}
    
     template <class T> void reverseN(struct Node<T> * & head, int k, struct Node<T> * &   kReversedHead, structNode<T> * & kReversedTail ) {
      struct Node<T> * ptr=head,*tmp;  
      int count=0;
      struct Node<T> *curr=head,*nextNode,*result=NULL; 
      while(curr && count <k) {
          count++; 
          cout <<"Curr data="<<curr->data<<"\t"<<"count="<<count<<"\n"; 
          nextNode=curr->next;  
          curr->next=kReversedHead; 
          kReversedHead=curr;
          if(count ==1 )  kReversedTail=kReversedHead; 
          curr=nextNode;
      }}
    
    0 讨论(0)
  • 2020-12-15 02:02

    (I'm assuming this is a singly linked list.) You can keep a temporary pointer (lets call it nodek) and advance it k times in a while loop. This will take O(k). Now you have a pointer to the start of the list and to the last element of the sublist. To reverse here, you remove from head which is O(1) and add to nodek which is O(1). Do this for all elements, so this is O(k) again. Now update root to nodek, and run the while loop on nodek again (to get the new position of nodek) and repeat this whole process again. Remember to do any error checking along the way. This solution will run at O(n) with only O(1) extra space.

    0 讨论(0)
  • 2020-12-15 02:04

    Here is a pseudo code.

    temp = main_head = node.alloc ();
    while ( !linked_list.is_empty () )
    {
        push k nodes on stack
        head = stack.pop ();
        temp->next = head;
        temp = head;
        while ( !stack.empty () )
        {
            temp->next = stack.pop ();
            temp = temp->next;
        }
    }
    

    I have made a demo implementation of this code. Pardon for the messy implementation. This will work for any value of k. Each k sized segment is reversed separately in the inner loop and the different segments are linked with each other in the outer loop before entering the inner one. temp traces the last node of the k sized sublist and head holds the next value of the next sublist, and we link them. An explicit stack is used to do the reversal.

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct _node {
      int a;
      struct _node *next;
    } node_t;
    
    typedef struct _stack {
      node_t *arr[128];
      int top;
    } stack_t;
    
    void stk_init (stack_t *stk)
    {
      stk->top = -1;
    }
    
    void push (stack_t *stk, node_t *val)
    {
      stk->arr[++(stk->top)] = val;
    }
    
    node_t *pop (stack_t *stk)
    {
      if (stk->top == -1)
       return NULL;
      return stk->arr[(stk->top)--];
    }
    
    int empty (stack_t *stk)
    {
      return (stk->top == -1);
    }
    
    int main (void)
    {
      stack_t *stk = malloc (sizeof (stack_t));
      node_t *head, *main_head, *temp1, *temp;
      int i, k, n;
    
      printf ("\nEnter number of list elements: ");
      scanf ("%d", &n);
      printf ("\nEnter value of k: ");
      scanf ("%d", &k);
    
      /* Using dummy head 'main_head' */
      main_head = malloc (sizeof (node_t));
      main_head->next  = NULL;
      /* Populate list */
      for (i=n; i>0; i--)
      {
        temp = malloc (sizeof (node_t));
        temp->a = i;
        temp->next = main_head->next;
        main_head->next = temp;
      }
    
      /* Show initial list */
      printf ("\n");
      for (temp = main_head->next; temp != NULL; temp = temp->next)
      {
        printf ("%d->", temp->a);
      }
    
      stk_init (stk);
    
      /* temp1 is used for traversing the list
       * temp is used for tracing the revrsed list
       * head is used for tracing the sublist of size 'k' local head
       * this head value is used to link with the previous
       * sublist's tail value, which we get from temp pointer
       */
      temp1 = main_head->next;
      temp = main_head;
      /* reverse process */
      while (temp1)
      {
        for (i=0; (temp1 != NULL) && (i<k); i++)
        {
          push (stk, temp1);
          temp1 = temp1->next;
        }
        head = pop (stk);
        temp->next = head;
        temp = head;
        while (!empty (stk))
        {
          temp->next = pop (stk);
          if (temp->next == NULL)
            break;
          temp = temp->next;
        }
      }
      /* Terminate list with NULL . This is necessary as
       * for even no of nodes the last temp->next points
       * to its previous node after above process
       */
      temp->next = NULL;
    
      printf ("\n");
      for (temp = main_head->next; temp != NULL; temp = temp->next)
      {
        printf ("%d->", temp->a);
      }
    
      /* free linked list here */
    
      return 0;
    }
    
    0 讨论(0)
  • 2020-12-15 02:07

    I like you recursion, although it may be not the best solution. I can see from your code that you think it deep when you design it. You're just one step away from the answer.

    Cause: You forget to return the new root node in your recursion case.

    if(temp!=NULL)
       noode->link=recrev(temp,c);
       // You need return the new root node here
       // which in this case is prev:
       // return prev;
     else
       return prev;
    
    0 讨论(0)
提交回复
热议问题