在给定大小的组中反转双向链表 |设置 2
给定一个包含n 个节点的双向链表。问题是反转列表中的每组k个节点。
例子:
Input: List: 10<->8<->4<->2, K=2
Output: 8<->10<->2<->4
Input: List: 1<->2<->3<->4<->5<->6<->7<->8, K=3
Output: 3<->2<->1<->6<->5<->4<->8<->7
递归方法:本文的 Set-1 中讨论了解决此问题的递归方法。在这里,我们正在讨论迭代方法。
迭代方法:这种方法混合了两种算法——反转双向链表和反转给定大小的组中的链表。函数reverseK()单独反转每个k大小的链表,并使用prevFirst指针连接它们,该指针跟踪反转后必然出现的节点。请按照以下步骤解决此问题:
- 如果N小于等于1,则返回head。
- 将变量prevFirst初始化为nullptr并将curr初始化为head。
- 将变量firstPass初始化为true。
- 遍历一个while循环,直到curr不等于null并执行以下任务:
- 将变量count初始化为0 。
- 首先将变量初始化为curr,将 next和prev初始化为null。
- 遍历一个while循环,直到curr不等于null并且count小于K并执行以下任务:
- 将next的值设置为curr->next。
- 如果count等于0 ,则将curr->next设置为null ,否则将 curr->next设置为curr->prev。
- 将curr->prev设置为next,prev设置为curr , curr设置为next。
- 将count的值增加1。
- 如果firstPass为true ,则将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)