61.旋转链表
一、题目描述
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
二、解题思路
一次旋转操作意味着: 先将链表闭合成环,然后将链表整体右移一次。因此只要能确定旋转后表头的位置,即可得到旋转后的链表。
三、解法一:非成环法
思路:
实现时,先用数组记录链表各节点的值,再将原数组复制一次,拼接在末尾。
代码:
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (head == NULL)
return NULL;
//用数组记录链表中的值
vector<int> nums;
ListNode* p = head;
while (p != NULL)
{
nums.push_back(p->val);
p = p->next;
}
//复制原数组并拼接
int size = int(nums.size());
for (int i = 0; i < size; i++)
{
nums.push_back(nums[i]);
}
//确定新的表头,得到旋转链表
int rotation = k % size;
int start = size - rotation;
int end = start + size - 1;
ListNode *ret = new ListNode(nums[start]);
p = ret;
for (int i = start + 1; i <= end; i++)
{
p->next = new ListNode(nums[i]);
p = p->next;
}
p->next = NULL;
return ret;
}
};
四、解法二:成环法
思路:
找到相应的位置断开这个环,确定新的链表头和链表尾。
代码:
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (head == NULL)
return NULL;
if (head->next == NULL)
return head;
//将链表闭合成环
ListNode *oldTail = head;
int n;
for (n = 1; oldTail->next != NULL; n++)
{
oldTail = oldTail->next;
}
oldTail->next = head;
//寻找断开位置
ListNode *newTail = head;
for (int i = 0; i < n - 1 - k % n; i++)
{
newTail = newTail->next;
}
ListNode *newHead = newTail->next;
newTail->next = NULL;
return newHead;
}
};