给定一个链表,旋转链表,将链表每一个节点向右移动 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个结点,而后断开k+1和k个结点之间的联接将其分红两个链表。而后将先后两个链表调换一下位置从新链接起来。(固然当k大于链表长度的时候须要取模运算)code
1.计算链表的长度。
2.定义一个指针pPre指向头结点,移动k步。
3.定义一个指针pCur指向头结点,同时向前移动pPre和pCur指针直到pPre遍历完整个链表,此时pCur即为倒数第k个结点。
4.在第k个结点处断开链表,再将先后两个链表交换顺序后从新链接起来。blog
ListNode* rotateRight(ListNode* head, int k) { if (head == NULL || head->next == NULL) { return head; } ListNode* pPre = head; int count = 0; while (pPre != NULL) { pPre = pPre->next; count++; } ListNode* pCur = head; pPre = head; for (int i = 0; i < k % count; i++) { pPre = pPre->next; } if (pPre != NULL) { while (pPre->next != NULL) { pPre = pPre->next; pCur = pCur->next; } pPre->next = head; head = pCur->next; pCur->next = NULL; } return head; }
改进版:数学
ListNode* rotateRight(ListNode* head, int k) { if (head == NULL || k == 0) { return head; } int count = 1; ListNode* p = head; while (p->next) { count++; p = p->next; } int left = count - k % count; p->next = head; for (int i = 0; i < left; ++i) { p = p->next; } head = p->next; p->next = NULL; return head; }
1.解题的关键是如何将题目转化为找到倒数第k个结点
2.另一个巧妙的地方是循环向前移动两个指针的时候判断的是pPre->next是否为NULL,这样能够将pPre和pCur分别定位到断开链表后的的最后一个结点上,方便断开的链表进行联接。
3.改进版是我在网上看到别人的思路实现的。首先统计整个链表的长度,同时将一个指针指向链表的最后一个结点,而后将链表首尾联接起来,组成一个环,而后用数学的方法计算出正着数应该移动left步,而后将指向最后一个结点的指针移动left步,最后在这个位置将链表断开即获得结果。
有时候思路真的就是一层窗户纸
List