难度:中等
目录
一、问题描述
这里直接采用LeetCode上面的问题描述。
给你一个链表的头节点 head
,旋转链表,将链表每个节点向右移动 k
个位置。
下面给出示例:
提示:
- 链表中节点的数目在范围
[0, 500]
内 -100 <= Node.val <= 100
0 <= k <= 2 * 109
二、思路
1、解题思路
题目中说是旋转链表其实是将链表往右移动 k 个位置(尾部移动到头部)。所以,只需要计算往右移动了几个单位就可以了,这里我们可以从尾部开始看,移动的 k 个元素可以看作将尾部移动到头部 k 个元素,而要找到移动 k 个元素后当前的头节点,就先要求出当前链表的大小。
因此首先遍历链表的大小记为:moveNode 顺便找到尾结点即为 tail,然后可以根据公式 moveNode -= (k % moveNode); 求得移动k位后头节点所处的位置。在此之前需要记录头节点,然后移动到 偏移后头节点的位置并且将该头节点与其前面一个结点断开(否则会产生循环链表)。
最后将 tail 指向刚开始的头节点即可,返回当前头结点。
这里需要注意:k == 0 的情况直接返回该链表即可,还有 k % moveSize == 0 的时候也是直接返回该链表即可。
三、解题
1、代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* rotateRight(struct ListNode* head, int k){
if(!head || !k){ //空结点 直接返回
return head;
}
struct ListNode* tail = head;
int moveNode = 1;
while(tail->next){
tail = tail->next;
moveNode++;
}
if(moveNode < 2 || !(k % moveNode)){ //结点数小于2直接返回
return head;
}
//计算偏移位置
moveNode = moveNode - (k % moveNode);
struct ListNode* temp = head;
while(moveNode){ //遍历到偏移位置
if(moveNode == 1){ //断开链表
struct ListNode* node = head;
head = head->next;
node->next = NULL;
}else{
head = head->next;
}
moveNode--;
}
//尾指针指向头部
tail->next = temp;
//从断开处返回结点
return head;
}
2、时间复杂度and空间复杂度
时间复杂度:
空间复杂度: