24. 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
解题
递归解法
设定first节点和second节点,若传入节点为空或下一个为空,则停止交换;
若两者都不为空,则前一个节点的next指向后一个几点的second,当前second的next指向当前节点的first,返回当前second,即为反转后两者的新的头节点;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head||!head->next) return head;
ListNode* firstnode = head;
ListNode* secondnode =head->next;
firstnode->next= swapPairs(secondnode->next);
secondnode->next=firstnode;
return secondnode;
}
};
递推解法(空间复杂度降至O(1))
一个节点保存头;
每次用previos节点,first节点和second节点,将previous节点指向second节点,first节点指向second节点的下一个,second节点指向fisrt节点,完成一对交换,且将该组头节点传至previos,在进行下一对交换时,previous=first,为下一组交换头节点的接收位置,head=first->next,为下一组交换的交换起点;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//三个指针,另一个保存头节点
ListNode dummy;
dummy.next=head;
ListNode *prev=&dummy;
ListNode * first;
ListNode * second;
while(head&&head->next)
{
first=head;
second=head->next;
prev->next=second;
first->next=second->next;
second->next=first;
prev=first;
head=first->next;
}
return dummy.next;
}
};
25. K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解题
每隔K个数反转链表(从反转起点到反转终点必须要有k个数),常数额外空间(迭代递推)。
与反转两个数的迭代算法类似,先找到反转的头节点head,反转尾节点rear,若rear不为Null,说明可以完成这一段反转,则
(1)将从head到rear之间的节点全部反转
需要用到first,second和tmp三个指针,first指向反转头节点,second反转尾节点,tmp指向second后面的节点(不然反转second会导致后面节点丢失);
进行k-1次反转——反转k个数;
ListNode *tmp;
first=head;
ListNode *second=first->next;
for(int m=0;m<k-1;m++) //从first到rear全部逆序
{
tmp=second->next;
second->next=first;
first=second;
second=tmp;
}
(2)反转后原来rear后面的节点丢失,所以反转前也要保存rear->next节点;
ListNode * p=rear->next;
(3)将rear节点传递给一开始的previos指针;
head节点下一个为原来rear的下一个节点p;
prev->next=rear;//传出的头节点为rear
head->next=p;
(4)为下一次反转做准备;
需要指向下一个传出的rear的节点为当前head,故prev=head;
下一个反转起点为前一个rear的next,故head=p;
重制rear,需要k-1次循环,找到head后面第k个数,故rear=p,然后k-1次next,若为null,则不会进行下一次反转,推出循环;
prev=head;
head = p;
rear=p; //关键点,rear后移
for(int t=0;t<k-1;t++)
{
if(rear){
rear=rear->next; //要交换的最后一个节点
}
}
完整代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummy;
ListNode *prev= &dummy;
prev->next=head;
ListNode *first;
ListNode *rear=head;
int i=0;
while(i<k-1&&rear)
{
rear=rear->next; //要交换的最后一个节点
i++;
}
while(head&&rear)
{
ListNode * p=rear->next;
ListNode *tmp;
first=head;
ListNode *second=first->next;
for(int m=0;m<k-1;m++) //从first到rear全部逆序
{
tmp=second->next;
second->next=first;
first=second;
second=tmp;
}
prev->next=rear;//传出的头节点为rear
head->next=p;
prev=head;
head = p;
rear=p; //关键点,rear后移
i=0;
while(i<k-1&&rear)
{
rear=rear->next; //要交换的最后一个节点
i++;
}
}
return dummy.next;
}
};
优化思路+优化代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummyhead;
dummyhead.next=head;
ListNode* start=&dummyhead;
ListNode *first=head;
ListNode * second;
ListNode * tmp;
while(1){
//检查能否找到第k个点
tmp=first;
int n=k-1;
while(tmp&&n) {
tmp=tmp->next;
n--;
}
if(!tmp) break;
//检查能否找到第k个点
second=first->next;
for(int i=1;i<k;i++) {
tmp=second->next;
second->next=first; //first保存在start->next中
first=second;
second=tmp;
}
start->next->next=second;
tmp=start->next;
start->next=first;
start=tmp;
first=tmp->next;
}
return dummyhead.next;
}
};


被折叠的 条评论
为什么被折叠?



