关于旋转链表的OJ题的一些总结
Posted 正义的伙伴啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于旋转链表的OJ题的一些总结相关的知识,希望对你有一定的参考价值。
旋转链表OJ题
引入问题
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解法一
刚开始做这题我用的是最铸币的方法,也是最容易想到的方法,多指针方法,然后通过循环遍历整个链表,这里的循环条件使n3不为NULL
设置4个指针分别指向要交换的两个节点和下一个要交换的两个节点
接下来这部就是进行交换,但是注意n1要指向n3,因为n3是下一个交换过后的头节点
然后就要进行一个指针的自增,但是自增的过程中又会出现两种情况的尾巴
- 节点是奇数个
我的处理方法是p和n3分别向后移动两个使p为多出来的节点,n3为空节点 - 节点是偶数个
我的处理方法是p向后移动两位,n3先后移动一位指向空节点
这样处理的结果就是:出循环在把n2的下一个节点指向n1,n1的下一个节点指向p,这里p就包含了奇数和偶数的两种尾巴
最后返回Newhead就结束了
但是这里还要注意两种特殊情况:
- 输入的是空指针
- 定义的时候要判断节点数是不是大于4个节点
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* swapPairs(struct ListNode* head){
if(head==NULL || head->next==NULL)
return head;
struct ListNode *newhead=head->next;
struct ListNode*n1=head;
struct ListNode*n2=head->next;
struct ListNode*p=n2->next;
struct ListNode*n3=NULL;
if(p==NULL)
n3=NULL;
else
n3=n2->next->next;
while(n3)
{
n2->next=n1;
n1->next=n3;
n1=p;
n2=n3;
if(n3->next)
{
n3=n3->next->next;
}
else
{
n3=n3->next;
}
p=p->next->next;
}
n2->next=n1;
n1->next=p;
return newhead;
}
解法二(简化)
但是这种方法并不是最优的解法,下面介绍一下递归法
我们发现其实我们实现的内容是重复的,这就可以用递归的思想
传过来的头节点前两个进行交换,返回交换后的头节点地址,并把第三个节点传给函数,当作下次递归的头节点。
递归结束的条件就是节点数小于2
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* swapPairs(struct ListNode* head){
struct ListNode*n1=head;
if((n1==NULL) || (n1->next==NULL))
return n1;
struct ListNode*n2=head->next;
struct ListNode*n3=n2->next;
n2->next=n1;
n1->next=swapPairs(n3);
return n2;
}
这种方法就比第一种简洁多了
问题提升
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
你可以设计一个只使用常数额外空间的算法来解决此问题吗?
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
原题
这个问题就是上一个问题的升级版
首先我们要找到进入递归的条件:链表的节点数要大于k
我们先遍历一遍数组并找到第K+1个节点的地址Next(下一次递归的头节点),并开始循环,循环结束的条件是n3!=Next
循环结束将n2的下一个节点指向n1
进入下一次递归
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseKGroup(struct ListNode* head, int k){
if(k<=1)
return head;
int size=0;
struct ListNode*p=head;
struct ListNode*NEXT=NULL;
while(p)
{
if(size==k)
NEXT=p;
p=p->next;
size++;
}
if(size<k)
return head;
else
{
struct ListNode*n3=head->next->next;
struct ListNode*n2=head->next;
struct ListNode*n1=head;
while(n3!=NEXT)
{
n2->next=n1;
n1=n2;
n2=n3;
n3=n3->next;
}
n2->next=n1;
head->next=reverseKGroup(NEXT,k);
return n2;
}
}
欢迎大家提供不同的想法!
以上是关于关于旋转链表的OJ题的一些总结的主要内容,如果未能解决你的问题,请参考以下文章