题目描述
题目分析
很容易发现,如果k是n的整数倍,相当于没有移动。这样直接对k%n使得k在一个可以接受的范围。
因为是顺序移动,各元素之间的相对位置保持不变,所以就想着将链表先变成一个环。然后再移动头指针,最后再断开。
头指针我们只能向后(右)移动,但是头指针的向右移动相当于整个链表向左移动,因此我们要将头指针移动n-k次,这样和向右移动k次链表的效果相同。
得到头指针后我们再将链表断开。我这里用了一种比较笨的方法,是在头指针的基础上再移动链表的长度,看题解才发现,原来尾指针就在头指针的前面,我只要保存尾指针,移动次数为n-k-1
。马达马达打内
AC代码
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* rotateRight(ListNode* head, int k) {if (head == nullptr || head->next == nullptr) return head;int n = 1;ListNode *p = head;while (p->next != nullptr) {++n;p = p->next;}k %= n;if (k == 0) return head;k = n - k;p->next = head;while (k--) {head = head->next;}p = head;--n;while (n--) {p = p->next;}p->next = nullptr;return head;}
};
需要注意的是,在遍历链表的时候,是使得指针指向当前节点还是指向当前节点的前一个节点是有讲究的,单纯的遍历的话可能不需要考虑,但是我们要获得尾指针来形成环,则必须保存的是当前节点的前一个节点。
这些细节能够显示代码的能力,如果思考的不够深入就会犯错。
题解代码
class Solution {
public:ListNode* rotateRight(ListNode* head, int k) {if (k == 0 || head == nullptr || head->next == nullptr) {return head;}int n = 1;ListNode* iter = head;while (iter->next != nullptr) {iter = iter->next;n++;}int add = n - k % n;if (add == n) {return head;}iter->next = head;while (add--) {iter = iter->next;}ListNode* ret = iter->next;iter->next = nullptr;return ret;}
};