题目分析:
- 给定一个链表,从链表尾端数k个节点位置,从该位置开始到结尾和之前的那部分对调。实质为链表的在某个位置旋转操作。
解题思路:
方法1:将链表链接成环再旋转
1)遍历链表,将链表的表尾和链表的表头相连,同时记录链表的表长
2)计算链表旋转后的处于的起始位置,然后从头遍历链表到逆转的位置前一个节点位置,即(len - k - 1)处;
3)记录链表的新表头,并断开环状链表即可。
方法2:直接定位旋转
1)遍历链表,找k所在的位置
2)遍历接受后,判断当前cur节点是否为空,如果为空,则可能是k值大于len导致,故令k = k % len,然后从头遍历链表到k - 1位置;否则直接处理步骤3);
3)从表头开始遍历链表,找到旋转所在位置的前一个元素位置;
4)将链表的表尾与表头相连接,然后记录新的表头所在的位置,同时将新的链表的表尾置空,返回新链表即可。
注意:实现过程中,注意对k取特殊值的处理即可。
实现程序
// 方法1:先将链表链接成环再旋转 ListNode *rotateRight1(ListNode *head, int k) { if (head == NULL || k == 0) return head; struct ListNode *p = head; // 统计链表长度 int len = 1; while (p->next != NULL) { p = p->next; len++; } // 将链表链接成环 p->next = head; // 计算实际的位置k if (k >= len) k = k % len; if (k == 0) { p->next = NULL; return head; } // 从表头遍历链表,定位到逆转的前一个位置值 int i = 1; p = head; while (i < len - k) { p = p->next; i++; } // 记录逆转后的头结点 head = p->next; // 断开环状链表 p->next = NULL; return head; } // 方法2:直接查找位置,进行相关旋转 ListNode *rotateRight(ListNode *head, int k) { // 特殊情况处理 if (head == NULL || k == 0) return head; // pre用于记录最后旋转的位置 struct ListNode *pre = head; // 遍历用于找位置 struct ListNode *cur = head; int count = 0; // 遍历链表寻找k位置 while (cur != NULL && count < k) { cur = cur->next; count++; } // 已经遍历到链表的尾部,可能count未达到k,此时count为链表长度 if (cur == NULL) { // 计算真正k的位置 k = k % count; cur = head; count = 0; // 从表头遍历,找到真正的k位置 while (cur != NULL && count < k) { cur = cur->next; count++; } } // 找到为逆转所在的位置,即len - k位置 while (cur->next != NULL) { pre = pre->next; cur = cur->next; } // 将链表首尾相接 cur->next = head; // 记录新的表头位置 head = pre->next; // 新链表的表尾置空 pre->next = NULL; // 返回新链表 return head; }