1. 原题链接:https://leetcode.com/problems/rotate-list/
2. 解题思路
- 对于链表涉及到反转、倒置等操作,一般都需要两个指针:prev、cur
- 根据翻转的规则,当翻转次数刚好是链表长度list_len的整数倍时,实际上翻转后的链表和未翻转的原链表是一样的
- 翻转次数k >= 0,由于k的大小不确定,当k是list_len的整数倍时,直接返回(因为通过k次翻转后,还是和原链表一样);否则,实际需要翻转的次数times是:(k % list_len)
- 因此,prev指向第(list_len - times)个节点,cur指向第(list_len - times + 1)个节点
- 采用头插法将cur指向的链表插入到原链表的头部
3. 算法
- 统计链表长度为list_len
- 判断k是不是list_len的整数倍
- 确定prev指针的位置,也就是第(list_len - times)个节点
- 确定cur指针的位置,也就是prev->next指向的节点
- 找到原链表的尾节点tail
- 采用头插法进行翻转
4. 实现
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} };
class Solution { public: ListNode* rotateRight(ListNode* head, int k) { if(head == NULL) return head; int list_len = 0; for(ListNode *tmp = head; tmp != NULL; tmp = tmp->next){ list_len++; } if(k % list_len == 0) return head; int end = list_len - (k % list_len); ListNode *prev = head; for(int i = 1; i < end; i++){ prev = prev->next; } ListNode *cur = prev->next; ListNode *tail = cur; while(tail != NULL && tail->next != NULL){ tail = tail->next; } prev->next = tail->next; tail->next = head; return cur; } };
//tricky solution class Solution { public: ListNode* rotateRight(ListNode* head, int k) { if(head == NULL) return head; int list_len = 1; ListNode *tail = head; for(; tail->next != NULL; tail = tail->next){ list_len++; } if(k % list_len == 0) return head; int end = list_len - (k % list_len); ListNode *prev = head; for(int i = 1; i < end; i++){ prev = prev->next; } ListNode *cur = prev->next; tail->next = head; //tricky: 首尾相连,构成环 prev->next = NULL; //prev也就是翻转后链表的尾节点,因此从此处将环打开 return cur; } };
来源:https://www.cnblogs.com/wengle520/p/12313186.html