25. K 个一组翻转链表
难度困难1998收藏分享切换为英文接收动态反馈
给你链表的头节点 head
,每 k
个节点一组进行翻转,请你返回修改后的链表。
k
是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k
的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 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]
提示:
- 链表中的节点数目为
n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:你可以设计一个只用 O(1)
额外内存空间的算法解决此问题吗?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseKGroup(struct ListNode* head, int k)
{
//创建是那个指针 s记录反转之后的头节点 e记录反转之后的尾节点 c要反转的下一个节点
struct ListNode* ptrStart;
struct ListNode* ptrEnd;
struct ListNode* ptrCurr;
if(head == NULL)
{
return head;
}
//如果头节点不为空 但所有节点之和不等于k也就不反转 直接返回head
ptrCurr = head;
for(int i = 0;i<k;i++)
{
if(ptrCurr != NULL)
{
ptrCurr = ptrCurr->next;
}
else{
return head;//遇到空就返回头节点
}
}
//将k个元素反转 首先要明白 两个元素进行翻转需要进行1此 以此类推 k个元素 需要k-1次
ptrStart = head;
ptrEnd = ptrStart;
ptrCurr = ptrStart->next;
for(int i = 1;i<k;i++)
{
if(ptrCurr)
{
ptrEnd->next = ptrCurr->next;
ptrCurr->next = ptrStart;
ptrStart = ptrCurr;
ptrCurr = ptrEnd->next;
}
}
ptrEnd->next = reverseKGroup(ptrCurr,k);//递归 看起来还是挺简洁的
return ptrStart;
}
思路理解
对于这个递归 他向下归的时候 就对k个节点进行了翻转 达到递归条件返回时 只返回了头节点 也就是S 或者head 将返回的节点连接到E->next 就达到了k个节点的翻转
206. 反转链表
难度简单3107收藏分享切换为英文接收动态反馈
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
提示:
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
struct ListNode* reverseList(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return head;
}
struct ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
这个递归就是先归到链表末尾 将最后一个节点作为头节点 newhead (记录翻转后的头节点)上一层函数调用中的head 是指向倒数第二个节点的 所以head->next->next 就是最后一个节点中存放下一个节点的指针 让倒数第一个节点指向倒数第二个节点 再将倒数第二个节点指向空 达到了一次翻转
递归调用个人感觉就像是用调用自身的那部分将整个函数划分两部分
第一部分 :就是向下递归时要做什么
第二部分 :就是向上递归时要做什么
再来个递归条件 什么时候停止 我感觉还是 考虑好第一部分 和 第二部分 在这个过程中你肯定会考虑到递归条件是什么
确实不太好想