K个一组反转
1.直接一个链表,反转。返回反转后的头结点。
例子:1->2->3 ; return 3->2->1;
#include <bits/stdc++.h> using namespace std; struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {}; ListNode(int _val) : val(_val), next(nullptr){}; };
//把链表反转
ListNode *reverse(ListNode *head) {
if (head == nullptr) return nullptr;
ListNode *pre= new ListNode(0);
ListNode *cur = head;
while (cur != nullptr) {
ListNode *nex = cur->next;
cur->next = pre;
pre = cur;
cur = nex;
}
return pre;
}
2.
//k个链表反转;
//递归版本,认为函数reversekj就可以实现k个反转,
例子:1->2->3->4;k=3;return :3->2->1->4;
问题是怎么把收尾连起来;递归调用,return 头;
ListNode *reversek(ListNode *head, int k) { //把尾巴结点设为开头,不直接操作head的原因是,这个是反转之后的尾巴,需要用于接下一个头; ListNode *tail = head; //让尾巴走k步 for (int i = 0; i < k; i++) { if (tail != nullptr) tail = tail->next; //走不到k步就说明,没法反转;那就不反转,把头返回就可以 else return head; } //此时tail已经是下一个的开头了; //给一个开头的结点和呀结点,进行反转准备 ListNode *pre = nullptr; ListNode *cur = head; //在这k里面走, while (cur != tail) { //进行反转 ListNode *nex = cur->next; cur->next = pre; pre = cur; cur = nex; } //反转结束,此时cur== tail,pre记录的是需要返回的头结点了;需要递归调用,让下一个头进去; //需要考虑怎么连起来呢?因为返回的是新头,只需要让这次的尾巴接上之前的新头就可以了; head->next = reversek(tail, k); return pre; }
3.逆序反转k个一组链表
例子:1->2->3->4->5->6->7->8->9->10;K=3
结果:1->4->3->2->7->6->5->10->9->8;
因为要逆序反转,那么要知道链表的长度;先遍历一遍链表,得到需要舍弃多少个头结点不需要反转操作的;之后和第二种情况一样。
//k个链表逆序反转;1-》2-》3->4->5->6->7->8; k=3;结果是:1-》2-》5-》4->3->8->7->6; //和正序的不同时,需要把前面的一些跳过,那么就需要知道需要跳过多少个;遍历一遍链表知道有多少长。 ListNode * rereversek(ListNode * root,int k){ if(root == nullptr) return root; ListNode * head = root; ListNode * cur = head; //记录链表的长度,有多少个节点 int cn = 0; while(cur!= nullptr){ cur= cur->next; ++cn; } //需要跳过的个数; int n = cn % k; if(n==0) return reversek(head,k); else { ListNode *curr = head; while (n-- > 0) { curr = curr->next; } head->next = reversek(curr, k); return head; } }