假设存在有一个链表,每过m个节点设为一组,然后把他们进行翻转。
请你返回翻转后的链表。
说明:
- m是一个正整数,它的值<= 链表的长度
- 若是节点的总数不是m的不为m的整数倍,那么后面剩余的节点请保存原有顺序。
- 设计一个只是用常数额外空间的算法来解决此问题
- 不能只单纯改变节点内部的值。而需要实际进行节点的交互。
示例结果1:
输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
示例结果2:
输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]
示例结果3:
输入:head = [1,2,3,4,5], k = 1
输出:[1,2,3,4,5]
示例结果4:
输入:head = [1], k = 1
输出:[1]
设计思路:
第一步:找到小组里尾结点的指针->groupTail
第二步:遍历找到尾结点的前一个结点->prevTail
第三步:groupTail的next指针指向prevTail
groupTail指向prevTail,依次向前推进,重复以上操作…
最后:改变头节点的指向为尾节点的指向
代码如下:
#includeusing namespace std; //Definition for singly-linked list. struct LinkNode { int val; LinkNode* next; LinkNode() : val(0), next(nullptr) {} LinkNode(int x) : val(x), next(nullptr) {} LinkNode(int x, LinkNode* next) : val(x), next(next) {} }; // KLinkSolution -- linkList operation class KLinkSolution { private: LinkNode* head; //头节点 LinkNode* tail; //尾结点 LinkNode* curr; //现在的位置 int cnt; //链表的大小 //初始话链表 void init() { curr = tail = head = new LinkNode(); cnt = 0; } //释放链表 void removeAll() { while (head != NULL) { curr = head; head = head->next; delete curr; } } public: //构造函数 KLinkSolution() { init(); } //析构函数 ~KLinkSolution() { removeAll(); } //清除链表 void clear() { removeAll();init(); } //获取链表的头节点 //返回:头节点的指针 LinkNode* getHead() { return head; } //获取链表的尾结点 //返回:尾结点的指针 LinkNode* getTail() { return tail; } //在链表的末尾添加元素 void append(const int& it) { tail = tail->next = new LinkNode(it, NULL); cnt++; } //获取链表节点的前一个节点 //参数:节点的指针node //返回值:节点的前一个节点的指针 LinkNode* prevNode(LinkNode* node) { if (node == head) return node; LinkNode* temp = head; while (temp->next != node) temp = temp->next; return temp; } //打印链表 void print() const { LinkNode* temp = head; while (temp->next != NULL) { temp = temp->next; cout << temp->val << " "; } } //反转一个小组的链表 //只用常数额外空间,用节点的交互的方法进行反转 //参数:当前小组的头指针groupHead,一个小组的节点数k //返回:下一个小组的头指针 LinkNode* reverseKGroup(LinkNode* groupHead, int k) { LinkNode* groupTail = groupHead; //小组的尾结点 LinkNode* prevHead = prevNode(groupHead); //小组头节点的前一个节点 for (int i = 1;i < k;i++) { groupTail = groupTail->next; } LinkNode* nextHead = groupTail; //反转后头节点应该指向的节点,即现在的尾结点 LinkNode* nextGroup = groupTail->next; //下一个小组的头节点 //尾结点往前遍历反转 while (groupTail != groupHead) { LinkNode* prevTail = prevNode(groupTail); groupTail->next = prevTail; groupTail = prevTail; } prevHead->next = nextHead; groupTail->next = nextGroup; //现在尾结点的位置是反转后尾结点的位置 return nextGroup; } }; int main() { KLinkSolution link; cout << "请输入链表的长度" << endl; int nodeNum; cin >> nodeNum; cout << "请输入链表节点的值" << endl; for (int i = 0; i < nodeNum; i++) { int temp; cin >> temp; link.append(temp); //添加链表的元素 } cout << "请输入多少个数值为一个反转小组" << endl; int k; cin >> k; int reverseNum = nodeNum / k; //计算出有多少个翻转小组 LinkNode* head = link.getHead()->next; //第一个翻转小组的头节点 for (int i = 0;i < reverseNum; i++) { head = link.reverseKGroup(head, k); } link.print(); }



