61. Rotate List**
https://leetcode.com/problems/rotate-list/
Title Description
Given a linked list, rotate the list to the right by k places, where k is non-negative.
Example 1:
Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL
Explanation:
rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL
Example 2:
Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL
Explanation:
rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL
C ++ implementation 1
I first introduced the latest thinking of it, then look at the previous practice.
The following code is the idea:
- First flip the entire list
- Before inverting
k
node, then flip thenum - k
nodes - Splicing two sub-lists
As the general idea, but there are some details to consider, in turn introduce the following:
- First,
k
there may be very large, if we know the number of nodes of the listnum
, we only need to deal withk %= num
the situation. In order to count the number of nodes linked list, this is done at the flip of this list, soreverse
increasing the functionint &num
of this parameter. - We only need to consider
k %= num
the situation, and if at this timek == 0
, then return directly to the original list, but the list in the first step has been flipped, so pay attention to flip back. - After entering the first two steps, originally intended to overturn ago
k
nodes, then flipped back ofnum - k
nodes, but will find that there is a problem that is not effectively splicing two lists, if you want to splice two lists, you need to find the last before a child node of the list, of course, also possible to do so, but do not feel very elegant. - Thus, another way is to first flip the back of
num - k
nodes after completion of rollover effect is as follows:
- After the third step, you need to flip
5->4
, and let the5
point1
. In fact, this idea andreverse
function of the logic is the same.
But there is a need to pay attention to detail,head
most move to4
, equivalent to3
a head end, we need to useend = p->next
first3
saved toend
the , but it can not bewhile
used directly in the cyclehead != p->next
; it is because the node4
last change, the corresponding p will change, leading to the finalp->next
they no longer point 3 below with a brief description of FIG step:
class Solution {
private:
ListNode* reverse(ListNode *head, int &num) {
ListNode *prev = nullptr;
while (head) {
auto tmp = head->next;
head->next = prev;
prev = head;
head = tmp;
num += 1;
}
return prev;
}
public:
ListNode* rotateRight(ListNode* head, int k) {
if (!head || !head->next) return head;
int num = 0;
// 第一步
head = reverse(head, num);
k = k % num;
if (k == 0) return reverse(head, num);
auto p = head;
while (--k) p = p->next;
// 第二步
auto rlist = p->next;
rlist = reverse(rlist, num);
// 第三步
auto end = p->next;
while (head != end) {
auto tmp = head->next;
head->next = rlist;
rlist = head;
head = tmp;
}
return rlist;
}
};
2 in C ++
Two years ago, the code:
Idea: use recursion can be very simple solution This question, if you want to list the rotation k times, it can be rotated in k - 1 on the basis of the list of the last node at the head of the list, so get the k-times list. but there optimization is important to note, otherwise it will report a timeout, after all, may be large k, we observe that, if k is divisible by the number of nodes in the list, then the list will be rotated original list itself.
class Solution {
private:
ListNode* rotateRight(ListNode *head, int n, int k) {
// 如果 k 能整除 n, 那么直接返回链表本身
if ((k % n) == 0) return head;
// 否则只要在第 k-1 次旋转得到的链表的基础上, 做一些简单的操作即可.
// 注意 while 循环中判断 ptr->next->next 是否存在, 这样是为了让
// ptr 最终的值是倒数第二个节点.
head = rotateRight(head, n, k - 1);
auto ptr = head;
while (ptr->next && ptr->next->next)
ptr = ptr->next;
auto tmp = ptr->next;
ptr->next = nullptr;
tmp->next = head;
head = tmp;
return head;
}
public:
ListNode* rotateRight(ListNode* head, int k) {
if (!head || !head->next) return head;
// 用 n 统计链表中节点的个数
int n = 0;
auto ptr = head;
while (ptr) {
ptr = ptr->next;
++ n;
}
return rotateRight(head, n, k);
}
};
C ++ implementation 3
From LeetCode Forum:
My clean C++ code, quite standard (find tail and reconnect the list)
Idea of this approach is to first determine the size of the list and find the last tail node, then inflicted cyclic chain tail->next = head
. According After k %= len
determining where disconnection list. (If not using an if statement k %= len
, the for loop the determination condition i < len - k
is actually i < len - k % len
.
Corresponds to the first ring, then left off. tail
To move len - k
step intuitive to think that, if the pointer can be moved backward, the backward movement k
step is most convenient; if you can not move backward, then we can move forward len - k
step.
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(!head) return head;
int len=1; // number of nodes
ListNode *newH, *tail;
newH=tail=head;
while(tail->next) // get the number of nodes in the list
{
tail = tail->next;
len++;
}
tail->next = head; // circle the link
if(k %= len)
{
for(auto i=0; i<len-k; i++) tail = tail->next; // the tail node is the (len-k)-th node (1st node is head)
}
newH = tail->next;
tail->next = NULL;
return newH;
}
};