链表顺时针旋转
给定一个单向链表和一个整数K ,任务是将链表顺时针向右旋转K 个位置。
例子:
Input: 1 -> 2 -> 3 -> 4 -> 5 -> NULL, K = 2
Output: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
Input: 7 -> 9 -> 11 -> 13 -> 3 -> 5 -> NULL, K = 12
Output: 7 -> 9 -> 11 -> 13 -> 3 -> 5 -> NULL
方法:旋转链表首先检查给定的 k 是否大于链表中的节点数。遍历链表,找到链表的长度然后与k比较,如果小于则继续,否则通过对链表长度取模来推导它在链表大小范围内。
之后从列表的长度中减去 k 的值。现在,问题已更改为链表的左旋转,因此请按照以下步骤操作:
- 将第 k 个节点的下一个更改为 NULL。
- 将最后一个节点的 next 更改为上一个头节点。
- 将头部更改为第 (k+1) 个节点。
为此,需要指向第 k 个节点、第 (k+1) 个节点和最后一个节点的指针。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
/* Link list node */
class Node {
public:
int data;
Node* next;
};
/* A utility function to push a node */
void push(Node** head_ref, int new_data)
{
/* allocate node */
Node* new_node = new Node();
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* A utility function to print linked list */
void printList(Node* node)
{
while (node != NULL) {
cout << node->data << " -> ";
node = node->next;
}
cout << "NULL";
}
// Function that rotates the given linked list
// clockwise by k and returns the updated
// head pointer
Node* rightRotate(Node* head, int k)
{
// If the linked list is empty
if (!head)
return head;
// len is used to store length of the linked list
// tmp will point to the last node after this loop
Node* tmp = head;
int len = 1;
while (tmp->next != NULL) {
tmp = tmp->next;
len++;
}
// If k is greater than the size
// of the linked list
if (k > len)
k = k % len;
// Subtract from length to convert
// it into left rotation
k = len - k;
// If no rotation needed then
// return the head node
if (k == 0 || k == len)
return head;
// current will either point to
// kth or NULL after this loop
Node* current = head;
int cnt = 1;
while (cnt < k && current != NULL) {
current = current->next;
cnt++;
}
// If current is NULL then k is equal to the
// count of nodes in the list
// Don't change the list in this case
if (current == NULL)
return head;
// current points to the kth node
Node* kthnode = current;
// Change next of last node to previous head
tmp->next = head;
// Change head to (k+1)th node
head = kthnode->next;
// Change next of kth node to NULL
kthnode->next = NULL;
// Return the updated head pointer
return head;
}
// Driver code
int main()
{
/* The constructed linked list is:
1->2->3->4->5 */
Node* head = NULL;
push(&head, 5);
push(&head, 4);
push(&head, 3);
push(&head, 2);
push(&head, 1);
int k = 2;
// Rotate the linked list
Node* updated_head = rightRotate(head, k);
// Print the rotated linked list
printList(updated_head);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
/* Link list node */
static class Node
{
int data;
Node next;
}
/* A utility function to push a node */
static Node push(Node head_ref, int new_data)
{
/* allocate node */
Node new_node = new Node();
/* put in the data */
new_node.data = new_data;
/* link the old list off the new node */
new_node.next = (head_ref);
/* move the head to point to the new node */
(head_ref) = new_node;
return head_ref;
}
/* A utility function to print linked list */
static void printList(Node node)
{
while (node != null)
{
System.out.print(node.data + " -> ");
node = node.next;
}
System.out.print( "null");
}
// Function that rotates the given linked list
// clockwise by k and returns the updated
// head pointer
static Node rightRotate(Node head, int k)
{
// If the linked list is empty
if (head == null)
return head;
// len is used to store length of the linked list
// tmp will point to the last node after this loop
Node tmp = head;
int len = 1;
while (tmp.next != null)
{
tmp = tmp.next;
len++;
}
// If k is greater than the size
// of the linked list
if (k > len)
k = k % len;
// Subtract from length to convert
// it into left rotation
k = len - k;
// If no rotation needed then
// return the head node
if (k == 0 || k == len)
return head;
// current will either point to
// kth or null after this loop
Node current = head;
int cnt = 1;
while (cnt < k && current != null)
{
current = current.next;
cnt++;
}
// If current is null then k is equal to the
// count of nodes in the list
// Don't change the list in this case
if (current == null)
return head;
// current points to the kth node
Node kthnode = current;
// Change next of last node to previous head
tmp.next = head;
// Change head to (k+1)th node
head = kthnode.next;
// Change next of kth node to null
kthnode.next = null;
// Return the updated head pointer
return head;
}
// Driver code
public static void main(String args[])
{
/* The constructed linked list is:
1.2.3.4.5 */
Node head = null;
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
int k = 2;
// Rotate the linked list
Node updated_head = rightRotate(head, k);
// Print the rotated linked list
printList(updated_head);
}
}
// This code is contributed by Arnub Kundu
Python3
# Python3 implementation of the approach
''' Link list node '''
class Node:
def __init__(self, data):
self.data = data
self.next = None
''' A utility function to push a node '''
def push(head_ref, new_data):
''' allocate node '''
new_node = Node(new_data)
''' put in the data '''
new_node.data = new_data
''' link the old list off the new node '''
new_node.next = (head_ref)
''' move the head to point to the new node '''
(head_ref) = new_node
return head_ref
''' A utility function to print linked list '''
def printList(node):
while (node != None):
print(node.data, end=' -> ')
node = node.next
print("NULL")
# Function that rotates the given linked list
# clockwise by k and returns the updated
# head pointer
def rightRotate(head, k):
# If the linked list is empty
if (not head):
return head
# len is used to store length of the linked list
# tmp will point to the last node after this loop
tmp = head
len = 1
while (tmp.next != None):
tmp = tmp.next
len += 1
# If k is greater than the size
# of the linked list
if (k > len):
k = k % len
# Subtract from length to convert
# it into left rotation
k = len - k
# If no rotation needed then
# return the head node
if (k == 0 or k == len):
return head
# current will either point to
# kth or None after this loop
current = head
cnt = 1
while (cnt < k and current != None):
current = current.next
cnt += 1
# If current is None then k is equal to the
# count of nodes in the list
# Don't change the list in this case
if (current == None):
return head
# current points to the kth node
kthnode = current
# Change next of last node to previous head
tmp.next = head
# Change head to (k+1)th node
head = kthnode.next
# Change next of kth node to None
kthnode.next = None
# Return the updated head pointer
return head
# Driver code
if __name__ == '__main__':
''' The constructed linked list is:
1.2.3.4.5 '''
head = None
head = push(head, 5)
head = push(head, 4)
head = push(head, 3)
head = push(head, 2)
head = push(head, 1)
k = 2
# Rotate the linked list
updated_head = rightRotate(head, k)
# Print the rotated linked list
printList(updated_head)
# This code is contributed by rutvik_56
C#
// C# implementation of the approach
using System;
class GFG
{
/* Link list node */
public class Node
{
public int data;
public Node next;
}
/* A utility function to push a node */
static Node push(Node head_ref,
int new_data)
{
/* allocate node */
Node new_node = new Node();
/* put in the data */
new_node.data = new_data;
/* link the old list off the new node */
new_node.next = (head_ref);
/* move the head to point
to the new node */
(head_ref) = new_node;
return head_ref;
}
/* A utility function to print linked list */
static void printList(Node node)
{
while (node != null)
{
Console.Write(node.data + " -> ");
node = node.next;
}
Console.Write("null");
}
// Function that rotates the given linked list
// clockwise by k and returns the updated
// head pointer
static Node rightRotate(Node head, int k)
{
// If the linked list is empty
if (head == null)
return head;
// len is used to store length of
// the linked list, tmp will point
// to the last node after this loop
Node tmp = head;
int len = 1;
while (tmp.next != null)
{
tmp = tmp.next;
len++;
}
// If k is greater than the size
// of the linked list
if (k > len)
k = k % len;
// Subtract from length to convert
// it into left rotation
k = len - k;
// If no rotation needed then
// return the head node
if (k == 0 || k == len)
return head;
// current will either point to
// kth or null after this loop
Node current = head;
int cnt = 1;
while (cnt < k && current != null)
{
current = current.next;
cnt++;
}
// If current is null then k is equal
// to the count of nodes in the list
// Don't change the list in this case
if (current == null)
return head;
// current points to the kth node
Node kthnode = current;
// Change next of last node
// to previous head
tmp.next = head;
// Change head to (k+1)th node
head = kthnode.next;
// Change next of kth node to null
kthnode.next = null;
// Return the updated head pointer
return head;
}
// Driver code
public static void Main(String []args)
{
/* The constructed linked list is:
1.2.3.4.5 */
Node head = null;
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
int k = 2;
// Rotate the linked list
Node updated_head = rightRotate(head, k);
// Print the rotated linked list
printList(updated_head);
}
}
// This code is contributed by PrinciRaj1992
Javascript
C++
#include
using namespace std;
class Node {
public:
int val;
Node* next;
Node(int d)
{
val = d;
next = NULL;
}
};
void build(Node*& head, int val)
{
if (head == NULL) {
head = new Node(val);
}
else {
Node* temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new Node(val);
}
}
Node* rotate_clockwise(Node* head, int k)
{
if (head == NULL) {
return NULL;
}
deque q;
Node* temp = head;
while (temp != NULL) {
q.push_back(temp);
temp = temp->next;
}
k %= q.size();
while (
k--) // popping from back and adding to it's front
{
q.back()->next = q.front();
q.push_front(q.back());
q.pop_back();
q.back()->next = NULL;
}
return q.front();
}
void print(Node* head)
{
while (head != NULL) {
cout << head->val << " -> ";
head = head->next;
}
cout << "NULL";
cout << endl;
}
int main()
{
Node* head = NULL;
build(head, 1);
build(head, 2);
build(head, 3);
build(head, 4);
build(head, 5);
int k = 2;
Node* r = rotate_clockwise(head, k);
print(r);
return 0;
}
输出:
4 -> 5 -> 1 -> 2 -> 3 -> NULL
时间复杂度: O(n),其中 n 是链表中的节点数。
基于 STL 的方法:
这个问题也可以使用C++ STL中提供的deque数据结构来解决
方法 :
初始化一个类型为 Node* 的双端队列并将链表推入其中。然后继续从它的后面弹出并将该节点添加到它的前面,直到操作数不等于 k。
C++
#include
using namespace std;
class Node {
public:
int val;
Node* next;
Node(int d)
{
val = d;
next = NULL;
}
};
void build(Node*& head, int val)
{
if (head == NULL) {
head = new Node(val);
}
else {
Node* temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new Node(val);
}
}
Node* rotate_clockwise(Node* head, int k)
{
if (head == NULL) {
return NULL;
}
deque q;
Node* temp = head;
while (temp != NULL) {
q.push_back(temp);
temp = temp->next;
}
k %= q.size();
while (
k--) // popping from back and adding to it's front
{
q.back()->next = q.front();
q.push_front(q.back());
q.pop_back();
q.back()->next = NULL;
}
return q.front();
}
void print(Node* head)
{
while (head != NULL) {
cout << head->val << " -> ";
head = head->next;
}
cout << "NULL";
cout << endl;
}
int main()
{
Node* head = NULL;
build(head, 1);
build(head, 2);
build(head, 3);
build(head, 4);
build(head, 5);
int k = 2;
Node* r = rotate_clockwise(head, k);
print(r);
return 0;
}
输出
4 -> 5 -> 1 -> 2 -> 3 -> NULL
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。