📌  相关文章
📜  在给定大小的组中反转双向链表 |设置 2

📅  最后修改于: 2022-05-13 01:56:06.962000             🧑  作者: Mango

在给定大小的组中反转双向链表 |设置 2

给定一个包含n 个节点的双向链表。问题是反转列表中的每组k个节点。

例子:

递归方法:本文的 Set-1 中讨论了解决此问题的递归方法。在这里,我们正在讨论迭代方法。

迭代方法:这种方法混合了两种算法——反转双向链表和反转给定大小的组中的链表。函数reverseK()单独反转每个k大小的链表,并使用prevFirst指针连接它们,该指针跟踪反转后必然出现的节点。请按照以下步骤解决此问题:

  • 如果N小于等于1,则返回head。
  • 将变量prevFirst初始化为nullptr并将curr初始化为head。
  • 将变量firstPass初始化为true。
  • 遍历一个while循环,直到curr不等于null并执行以下任务:
    • 将变量count初始化为0
    • 首先将变量初始化为curr,将 nextprev初始化为null。
    • 遍历一个while循环,直到curr不等于null并且count小于K并执行以下任务:
      • next的值设置为curr->next。
      • 如果count等于0 ,则将curr->next设置为null ,否则将 curr->next设置为curr->prev。
      • curr->prev设置为next,prev设置为currcurr设置为next。
      • count的值增加1。
      • 如果firstPasstrue ,则将head设置为next->prev并将firstPass 设置false。
      • 否则,将prevFirst->next设置为prev。
      • prevFirst设置为first。
  • 执行上述步骤后,打印head的值作为答案。

下面是上述方法的实现。

C++
// C++ program for the above approach
#include 
using namespace std;
 
// A linked list node
class Node {
public:
    int data;
    Node* next;
    Node* prev;
};
 
// Given a reference (pointer to pointer)
// to the head of a list
// and an int, inserts a new node on the
// front of the list.
void push(Node** head_ref, int new_data)
{
 
    // Allocate node
    Node* new_node = new Node();
 
    // Put in the data
    new_node->data = new_data;
 
    // Make next of new node as head
    // and previous as NULL
    new_node->next = (*head_ref);
    new_node->prev = NULL;
 
    // Change prev of head node to new node
    if ((*head_ref) != NULL)
        (*head_ref)->prev = new_node;
 
    // Move the head to point to the new node
    (*head_ref) = new_node;
}
 
// Given a node as prev_node, insert
// a new node after the given node
void insertAfter(Node* prev_node, int new_data)
{
 
    // Check if the given prev_node is NULL
    if (prev_node == NULL) {
        cout << "the given previous "
             << "node cannot be NULL";
        return;
    }
 
    // Allocate new node
    Node* new_node = new Node();
 
    // Put in the data
    new_node->data = new_data;
 
    // Make next of new node as next of prev_node
    new_node->next = prev_node->next;
 
    // Make the next of prev_node as new_node
    prev_node->next = new_node;
 
    // Make prev_node as previous of new_node
    new_node->prev = prev_node;
 
    // Change previous of new_node's next node
    if (new_node->next != NULL)
        new_node->next->prev = new_node;
}
 
// Given a reference (pointer to pointer) to the head
// of a DLL and an int, appends a new node at the end
void append(Node** head_ref, int new_data)
{
 
    // Allocate node
    Node* new_node = new Node();
 
    Node* last = *head_ref;
 
    // Put in the data
    new_node->data = new_data;
 
    // This new node is going to be the last node,
    // so make next of it as NULL
    new_node->next = NULL;
 
    // If the Linked List is empty,
    // then make the new
    // node as head
    if (*head_ref == NULL) {
        new_node->prev = NULL;
        *head_ref = new_node;
        return;
    }
 
    // Else traverse till the last node
    while (last->next != NULL)
        last = last->next;
 
    // Change the next of last node
    last->next = new_node;
 
    // Make last node as previous of new node
    new_node->prev = last;
 
    return;
}
 
// This function prints contents of
// linked list starting from the given node
void printList(Node* node)
{
    Node* last;
    while (node != NULL) {
        cout << " " << node->data << " ";
        last = node;
        node = node->next;
    }
}
 
Node* reverseK(Node* head, int k)
{
 
    // When head is NULL or linked list
    // has a single node we return
    if (head == NULL || head->next == NULL)
        return head;
 
    // PrevFirst pointer keeps track of
    // the node that is to be connected to each
    // reversed part.
    Node *prevFirst = NULL, *curr = head;
 
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    bool firstPass = true;
 
    while (curr != NULL) {
        int count = 0;
 
        // Next keeps track of the next node of curr
        // Prev keeps track of the previous node of curr
 
        Node *first = curr, *next = NULL, *prev = NULL;
        while (curr != NULL && count < k) {
 
            // Reversing the doubly linked list by just
            // swapping their next and prev pointers
            next = curr->next;
            if (count == 0)
                curr->next = NULL;
            else
                curr->next = curr->prev;
            curr->prev = next;
            prev = curr;
            curr = next;
            count++;
        }
        if (firstPass) {
 
            // Setting the head of the new linkedlist
            head = next->prev;
            firstPass = false;
        }
        else {
            prevFirst->next = prev;
        }
        prevFirst = first;
    }
    return head;
}
 
// Driver Code
int main()
{
 
    // Start with the empty list
    Node* head = NULL;
 
    // Insert 6. So linked list becomes 6->NULL
    append(&head, 6);
 
    // Insert 7 at the beginning. So
    // linked list becomes 7->6->NULL
    push(&head, 7);
 
    // Insert 1 at the beginning. So
    // linked list becomes 1->7->6->NULL
    push(&head, 1);
 
    // Insert 4 at the end. So linked
    // list becomes 1->7->6->4->NULL
    append(&head, 4);
 
    // Insert 8, after 7. So linked
    // list becomes 1->7->8->6->4->NULL
    insertAfter(head->next, 8);
 
    // list becomes 1->7->8->6->4->9->NULL
    append(&head, 9);
    head = reverseK(head, 2);
    printList(head);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// A linked list node
static class Node {
    int data;
    Node next;
    Node prev;
};
static Node head = null;
   
// Given a reference (pointer to pointer)
// to the head of a list
// and an int, inserts a new node on the
// front of the list.
static void push(int new_data)
{
 
    // Allocate node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as head
    // and previous as null
    new_node.next = head;
    new_node.prev = null;
 
    // Change prev of head node to new node
    if (head != null)
        head.prev = new_node;
 
    // Move the head to point to the new node
    head = new_node;
}
 
// Given a node as prev_node, insert
// a new node after the given node
static void insertAfter(Node prev_node, int new_data)
{
 
    // Check if the given prev_node is null
    if (prev_node == null) {
        System.out.print("the given previous "
            + "node cannot be null");
        return;
    }
 
    // Allocate new node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as next of prev_node
    new_node.next = prev_node.next;
 
    // Make the next of prev_node as new_node
    prev_node.next = new_node;
 
    // Make prev_node as previous of new_node
    new_node.prev = prev_node;
 
    // Change previous of new_node's next node
    if (new_node.next != null)
        new_node.next.prev = new_node;
}
 
// Given a reference (pointer to pointer) to the head
// of a DLL and an int, appends a new node at the end
static void append(int new_data)
{
 
    // Allocate node
    Node new_node = new Node();
 
    Node last = head;
 
    // Put in the data
    new_node.data = new_data;
 
    // This new node is going to be the last node,
    // so make next of it as null
    new_node.next = null;
 
    // If the Linked List is empty,
    // then make the new
    // node as head
    if (head == null) {
        new_node.prev = null;
        head = new_node;
        return;
    }
 
    // Else traverse till the last node
    while (last.next != null)
        last = last.next;
 
    // Change the next of last node
    last.next = new_node;
 
    // Make last node as previous of new node
    new_node.prev = last;
 
    return;
}
 
// This function prints contents of
// linked list starting from the given node
static void printList(Node node)
{
    Node last = new Node();
    while (node != null) {
        System.out.print(" " +  node.data+ " ");
        last = node;
        node = node.next;
    }
}
 
static Node reverseK(Node head, int k)
{
 
    // When head is null or linked list
    // has a single node we return
    if (head == null || head.next == null)
        return head;
 
    // PrevFirst pointer keeps track of
    // the node that is to be connected to each
    // reversed part.
    Node prevFirst = null, curr = head;
 
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    boolean firstPass = true;
 
    while (curr != null) {
        int count = 0;
 
        // Next keeps track of the next node of curr
        // Prev keeps track of the previous node of curr
 
        Node first = curr, next = null, prev = null;
        while (curr != null && count < k) {
 
            // Reversing the doubly linked list by just
            // swapping their next and prev pointers
            next = curr.next;
            if (count == 0)
                curr.next = null;
            else
                curr.next = curr.prev;
            curr.prev = next;
            prev = curr;
            curr = next;
            count++;
        }
        if (firstPass) {
 
            // Setting the head of the new linkedlist
            head = next.prev;
            firstPass = false;
        }
        else {
            prevFirst.next = prev;
        }
        prevFirst = first;
    }
    return head;
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Start with the empty list
    head = null;
 
    // Insert 6. So linked list becomes 6.null
    append( 6);
 
    // Insert 7 at the beginning. So
    // linked list becomes 7.6.null
    push(7);
 
    // Insert 1 at the beginning. So
    // linked list becomes 1.7.6.null
    push(1);
 
    // Insert 4 at the end. So linked
    // list becomes 1.7.6.4.null
    append( 4);
 
    // Insert 8, after 7. So linked
    // list becomes 1.7.8.6.4.null
    insertAfter(head.next, 8);
 
    // list becomes 1.7.8.6.4.9.null
    append( 9);
    head = reverseK(head, 2);
    printList(head);
 
}
}
 
// This code contributed by shikhasingrajput


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG{
 
  // A linked list node
  class Node {
    public int data;
    public Node next;
    public Node prev;
  };
  static Node head = null;
 
  // Given a reference (pointer to pointer)
  // to the head of a list
  // and an int, inserts a new node on the
  // front of the list.
  static void push(int new_data)
  {
 
    // Allocate node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as head
    // and previous as null
    new_node.next = head;
    new_node.prev = null;
 
    // Change prev of head node to new node
    if (head != null)
      head.prev = new_node;
 
    // Move the head to point to the new node
    head = new_node;
  }
 
  // Given a node as prev_node, insert
  // a new node after the given node
  static void insertAfter(Node prev_node, int new_data)
  {
 
    // Check if the given prev_node is null
    if (prev_node == null) {
      Console.Write("the given previous "
                    + "node cannot be null");
      return;
    }
 
    // Allocate new node
    Node new_node = new Node();
 
    // Put in the data
    new_node.data = new_data;
 
    // Make next of new node as next of prev_node
    new_node.next = prev_node.next;
 
    // Make the next of prev_node as new_node
    prev_node.next = new_node;
 
    // Make prev_node as previous of new_node
    new_node.prev = prev_node;
 
    // Change previous of new_node's next node
    if (new_node.next != null)
      new_node.next.prev = new_node;
  }
 
  // Given a reference (pointer to pointer) to the head
  // of a DLL and an int, appends a new node at the end
  static void append(int new_data)
  {
 
    // Allocate node
    Node new_node = new Node();
 
    Node last = head;
 
    // Put in the data
    new_node.data = new_data;
 
    // This new node is going to be the last node,
    // so make next of it as null
    new_node.next = null;
 
    // If the Linked List is empty,
    // then make the new
    // node as head
    if (head == null) {
      new_node.prev = null;
      head = new_node;
      return;
    }
 
    // Else traverse till the last node
    while (last.next != null)
      last = last.next;
 
    // Change the next of last node
    last.next = new_node;
 
    // Make last node as previous of new node
    new_node.prev = last;
 
    return;
  }
 
  // This function prints contents of
  // linked list starting from the given node
  static void printList(Node node)
  {
    Node last = new Node();
    while (node != null) {
      Console.Write(" " +  node.data+ " ");
      last = node;
      node = node.next;
    }
  }
 
  static Node reverseK(Node head, int k)
  {
 
    // When head is null or linked list
    // has a single node we return
    if (head == null || head.next == null)
      return head;
 
    // PrevFirst pointer keeps track of
    // the node that is to be connected to each
    // reversed part.
    Node prevFirst = null, curr = head;
 
    // FirstPass variable is used so that we
    // can mark head of the new linkedlist.
    bool firstPass = true;
 
    while (curr != null) {
      int count = 0;
 
      // Next keeps track of the next node of curr
      // Prev keeps track of the previous node of curr
 
      Node first = curr, next = null, prev = null;
      while (curr != null && count < k) {
 
        // Reversing the doubly linked list by just
        // swapping their next and prev pointers
        next = curr.next;
        if (count == 0)
          curr.next = null;
        else
          curr.next = curr.prev;
        curr.prev = next;
        prev = curr;
        curr = next;
        count++;
      }
      if (firstPass) {
 
        // Setting the head of the new linkedlist
        head = next.prev;
        firstPass = false;
      }
      else {
        prevFirst.next = prev;
      }
      prevFirst = first;
    }
    return head;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
 
    // Start with the empty list
    head = null;
 
    // Insert 6. So linked list becomes 6.null
    append( 6);
 
    // Insert 7 at the beginning. So
    // linked list becomes 7.6.null
    push(7);
 
    // Insert 1 at the beginning. So
    // linked list becomes 1.7.6.null
    push(1);
 
    // Insert 4 at the end. So linked
    // list becomes 1.7.6.4.null
    append( 4);
 
    // Insert 8, after 7. So linked
    // list becomes 1.7.8.6.4.null
    insertAfter(head.next, 8);
 
    // list becomes 1.7.8.6.4.9.null
    append( 9);
    head = reverseK(head, 2);
    printList(head);
 
  }
}
 
// This code is contributed by 29AjayKumar


输出
7  1  6  8  9  4 

时间复杂度: O(N)
辅助空间: O(1)