题目:
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
思路过程:
1、首先遍历整个链表,求出链表的长度n,并找出链表的尾节点tail。
2、由于k可能很大,所以我们令 k = k % n,然后再次从头节点head开始遍历,找到第n - k个节点p,那么1 ~ p是链表的前 n - k个节点,p+1 ~ n是链表的后k个节点。
3、接下来就是依次执行 tail->next = head,head = p->next,p->next = nullptr,将链表的后k个节点和前 n - k个节点拼接到一块,并让head指向新的头节点(p->next),新的尾节点即p节点的next指针指向null。
4、最后返回链表的新的头节点head。
C++:
#include<iostream>
#include<vector>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode(int x)
{
val = x;
next = nullptr;
}
ListNode(int x,ListNode* next)
{
val = x;
next = next;
}
};
class Solution
{
public:
ListNode* rotate(ListNode* head, int k)
{
if(head == nullptr || k == 0) return head;
int n = 0;
ListNode* tail; // 尾结点
for(ListNode* p=head; p != nullptr; p = p->next)
{
tail = p;
n++; // 链表长度
}
k = k % n;
ListNode* p = head;
// 倒数第 k 个节点,即正数第 n-k-1 为k节点的前一个节点
for(int i=0; i<n-k-1;i++)
{
p = p->next; // p为n-k个节点
}
tail->next = head; // 首尾环连接
head = p->next;
p->next = nullptr; // 断开环
return head;
}
};
python:
思路同上,即:预先遍历一遍链表,得到链表的节点个数n和链表的尾节点tail;然后再一次遍历找到切割节点的前一个节点(第n-k个节点),进行切割与拼接。
class ListNode(object):
def __init__(self,val = 0,next = None):
self.val = val
self.next = next
class Solution:
def rotate(self,head, k):
if not head: return head # 链表为空直接返回
node = head # 用于遍历链表和定位尾结点的节点
n = 1 # 统计链表的节点数,初始为1,表示头结点
while node.next != None: # 为了定位尾节点,应该以node.next为空作为终止条件
n += 1
node = node.next
k %= n
if k == 0: return head
tail = head # 暂存头节点
node = head # 重新遍历链表
while n > k+1:
node = node.next # 定位新头节点的前一个节点,即第n-k个节点
n -= 1
# 重新拼接[1, n - k]部分节点和[n - k + 1, n]部分节点,即变为[n - k + 1, n] + [1, n - k]
tail,next = head
new_head = node.next
node.next = None
return new_head