061. Rotate List

题目链接:https://leetcode.com/problems/rotate-list/description/

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

思路:

  • 根据题意,给定了一个单链表和一个非负整数k,对链表进行k次旋转操作。每次旋转操作都是将单链表的尾结点插入到当前单链表头结点前的位置。
  • 因为每次旋转操作中的插入操作部分都是要对头结点处进行操作,为了便于节点的插入,我们可以构造一个辅助节点指向链表的头结点。
  • 在每次旋转操作的过程中,我们所需要进行的操作可以分解为2个步骤:
    1. 步骤1为找到单链表的尾结点,此处应用一个结点指针指向尾结点前的节点(因为要改变此结点的指向,让其指向nullptr,该结点变为尾结点);
    2. 步骤1中找到的尾结点,要将其插入到单链表的头结点前,让该结点成为单链表的头结点。
  • 循环执行k次这样的操作即可。

  注意:如果按照上面描述的操作进行编码实现,会出现Time Limit Exceeded的问题。

      想到的可优化的部分是:对k次旋转操作部分进行优化,假设链表结点个数为n,即链表长度为n。

              则旋转操作次数为loop = k % n;

      因为链表进行旋转操作是以链表的长度n为周期的,即我们的旋转操作次数应小于链表的长度n。

      其他可优化的部分可以继续思考。未完待续!!!

      另外也要注意编码过程中的一些小细节,例如当单链表节点个数为1时,上面描述的步骤1可能会有逻辑错误(指针指向错误)。

    

编码如下

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* rotateRight(ListNode* head, int k) {
12         // 链表为空,则直接返回
13         if (head == nullptr) return head;
14         
15         int cnt = 0;        // 统计链表节点个数
16         ListNode *p = head;
17         while (p != nullptr)
18         {
19             cnt++;
20             p = p->next;
21         }
22         
23         int loop = k % cnt;     // 要进行旋转的次数
24         
25         // 辅助节点,永远指向链表的头结点
26         ListNode *pHead = new ListNode(-1);
27         pHead->next = head;
28         
29         ListNode *pre = nullptr;        // 指向待旋转节点的前一个节点
30         for (int i = 0; i < loop; ++i)     // 进行旋转操作计数
31         {
32             ListNode *pTemp = head;
33             while (pTemp->next != nullptr)
34             {
35                 pre = pTemp;
36                 pTemp = pTemp->next;
37             }
38             
39             if (pre == nullptr)        // 注意当链表长度为1时
40             {
41                 return head;
42             }
43             
44             pre->next = nullptr;     // pre成为指向链表尾结点的尾指针
45             
46             // 插入查找到的结点到链表的头结点前
47             pHead->next = pTemp;
48             pTemp->next = head;
49             head = pTemp;         // head永远指向链表的头结点
50         }  
51         
52         return head;
53     }
54 }; 

  

猜你喜欢

转载自www.cnblogs.com/ming-1012/p/9900698.html