LeetCode 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
解题
反转链表,和闭环的左移右移相似,所以可以把链表前后连接成环,然后在指定位置断开即可。唯一需要考虑的是根据向右移动K个位置找到应该断开的位置以及新的链表头。例如实例1,将链表看作{1-2-3-4-5-}样式的环形链表,向右移动2个位置,即应该在{3}、{4}两个节点处断开,节点{4}为新的链表头。但是链表只能从前向后遍历,因此我们实际考虑的是向左移动L-K个位置,同时考虑到K可能大于L,所以向右移动K个位置对应向左移动 ( L − 1 − K % L ) (L-1-K\%L) (L−1−K%L)个位置。所以我们要:
- 遍历链表获取链表长度以及最后一个节点
- 将链表闭合为一个环
- 计算断开位置并断开链表
- 返回新的链表头
以下是代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (head==nullptr || head->next == nullptr)
return head;
ListNode *cur_node(head);
int len = 1;
while (cur_node->next){
cur_node = cur_node->next;
++len;
}
cur_node->next = head;
k = len - k%len - 1;
cur_node = head;
while (k){
cur_node = cur_node->next;
--k;
}
head = cur_node->next;
cur_node->next = nullptr;
return head;
}
};
【其他思路】
把链表视作一个环是最简单最方便的方法,此外还可以借助先入后出的stack结构逆向从最后一个节点开始遍历K-1(注意K应该已经通过取余而小于L)个位置。当然这种方法使用了额外的空间,与前面方法相比没有优势,这里只提供思路。