1、 用栈分组翻转。单次翻转,时间复杂度o(n),空间复杂度o(k)。
#include<stack> using namespace std; class Solution { public: ListNode* reverseKGroup(ListNode* head, int k) { stack<ListNode *> stk; ListNode dummy = ListNode(0); dummy.next = head; // 哨兵节点 ListNode *pre = &dummy; while(head != nullptr) { int i = 0; for(i=0; i<k && head!=nullptr; i++) { stk.push(head); head = head->next; } if (i==k) { pre->next = stk.top(); stk.pop(); ListNode * cur = pre->next; while(!stk.empty()) { cur->next = stk.top(); stk.pop(); cur = cur->next; } pre = cur; // 这里把已翻转区间的右节点和未翻转的左节点连接,让区间不足的情况不用处理 pre->next = head; } else { while(!stk.empty()) { stk.pop(); } } } return dummy.next; } };
2、复用翻转链表前n个节点的能力(实现方法:递归)。每次分组翻转前,有前置的哑节点做定位,调用翻转链表前n个节点的函数,再拼接哑节点和翻转后的链表。时间复杂度o(n),空间复杂度o(k)
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param head ListNode类 * @param k int整型 * @return ListNode类 */ ListNode* reverseKGroup(ListNode* head, int k) { if(k<=1 || head == nullptr) { return head; } int n = 0; ListNode* cur = head; while(cur != nullptr) { n++; cur = cur->next; } ListNode dummy = ListNode(0); dummy.next = head; ListNode *pre = &dummy; while(n>=k) { n -= k; cur = pre->next; ListNode* newHead = reverseNLength(cur, k); pre->next = newHead; pre = cur; } return dummy.next; } ListNode* reverseNLength(ListNode* head, int n) { if(n<=1 || head == nullptr) { return head; } ListNode* next = head->next; ListNode* newHead = reverseNLength(next, n-1); head->next = next->next; next->next = head; return newHead; } };
- 复用翻转链表前n个节点的能力(实现方法: 头插法)。增加一个哑节点作为定位。时间复杂度o(n),空间复杂度o(1)
#include<stack> using namespace std; class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param head ListNode类 * @param k int整型 * @return ListNode类 */ ListNode* reverseKGroup(ListNode* head, int k) { stack<ListNode *> stk; ListNode dummy = ListNode(0); dummy.next = head; // 哨兵节点 ListNode *pre = &dummy; while(head != nullptr) { int i = 0; for(i=0; i<k && head!=nullptr; i++) { stk.push(head); head = head->next; } if (i==k) { while(!stk.empty()) { ListNode *top = stk.top(); stk.pop(); pre->next = top; pre = top; } // 翻转末尾将下一个区间的起始连起来,最后一段不需要翻转的情况就无需处理 pre->next = head; } else { while(!stk.empty()) { stk.pop(); } } } return dummy.next; } };