校招算法刷题笔记:链表之反转

这篇博客详细介绍了四种链表反转的算法:反转整个链表、反转链表前N个节点、链表内指定区间反转和K个节点一组反转链表。包括迭代和递归两种思路,并给出了相应的代码实现。
摘要由CSDN通过智能技术生成

题型

反转整个链表

反转链表前N个节点

链表内指定区间反转

K个节点一组反转链表


反转整个链表

思路1:

迭代,定义三个辅助链表节点指针pre、cur、nxt,pre为遍历链表时所在节点cur的前驱节点,nxt为cur的后驱节点。

步骤:

1.nxt指向cur下一个节点;

2. cur的下一个节点修改为pre;

3. pre指向当前节点cur;

4. cur指向nxt;

代码:

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode* pre=nullptr;
        ListNode* cur=pHead;
        ListNode* nxt=pHead;
        while(cur){
            nxt=cur->next;
            cur->next =pre;
            pre =cur;;
            cur =nxt;
        }
        return pre;
    }
};

思路2:

递归,定义一个函数,参数为链表头节点,返回值为反转链表的头节点。

步骤:

1.确定base case,head为空或者head的下一个节点为空,反转链表头节点为其本身,则返回head;

2.反转以head的下一个节点为头节点的链表,并返回新链表头节点

3. 设置head的后驱节点的下一个节点为head;

4. head下一个节点改为nullptr,即链表尾节点;

5. 返回新链表头节点;

代码:

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==nullptr || pHead->next==nullptr) return pHead;
        ListNode* head =ReverseList(pHead->next);
        pHead->next->next =pHead;
        pHead->next=nullptr;
        return head;
    }
};

反转链表前N个节点

思路:迭代or递归

迭代:反转整个链表相当于反转[头节点,nullptr],左闭右开,结束条件为cur==nullptr(右端点),那么反转前n个节点,需先找到第n+1个节点,将结束条件改为对应的节点即可。

递归:定义一个函数,参数为(head,n),返回反转前n个节点后的头节点。当n为1时,结果为其本身。先完成head节点后驱节点的前n-1个节点的反转,记录新头节点的后驱节点,将head后驱节点的下一个节点设置为head,head的下一个节点设置为新头节点的后驱节点,返回新头节点。

递归代码:

    ListNode* reverseN(ListNode* head,int n){
        if(n==1){
            return head;
        }
        ListNode* last= reverseN(head->next, n-1);
        ListNode* post=head->next->next;
        head->next->next=head;
        head->next =post;
        return last;
    }

链表内指定区间反转

思路:迭代 or递归

迭代:将链表的m位置到n位置之间的区间反转,找到m位置和n+1位置,然后使用反转链表的迭代方法即可。

递归:定义一个函数,参数为(head,m, n),返回链表的m位置到n位置之间的区间反转后的头节点。

1.base case,当m=1,即反转前n个节点,调用上文reverseN(head,n)即可。

2.当head向后一个节点移动,相当于要反转链表的[m-1,fn-1]区间,

3.将head下一个节点指向以head->next为头反转后的头节点,返回head;

递归代码:

class Solution {
public:

    ListNode* reverseBetween(ListNode* head, int m, int n) {
        // write code here
        if(m==1) {
            ListNode* l =reverseN(head,n);
            return l;
        }
        head->next = reverseBetween(head->next,m-1,n-1);
        return head;
    }
    ListNode* reverseN(ListNode* head,int n){
        if(n==1){
            return head;
        }
        ListNode* last= reverseN(head->next, n-1);
        ListNode* post=head->next->next;
        head->next->next=head;
        head->next =post;
        return last;
    }
};

K个节点一组反转链表

思路:迭代or反转

迭代:[1:k+1],[k+1:2k+1]....区间分别调用迭代方法反转。

递归:定义函数能实现k个节点一组反转链表,参数为(head,k)。

1.base case:以head为头的链表节点数是否小于k;

2.反转前k个节点,保存新头节点;

3.找到head之后的第k个节点,以其为head进行k个节点一组反转,并将其结果作为head的后驱节点;

4 返回新头节点;

递归代码:

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        // write code here
        ListNode* b=head;
        for(int i=0;i<k;i++){
            if(b==nullptr) return head;
            b =b->next;
        }
        ListNode* newhead=reverse(head,b);
        head->next =reverseKGroup(b,k);
        return newhead;
    }
    ListNode* reverse(ListNode* start,ListNode* end){
        ListNode* pre=nullptr;
        ListNode* cur=start;
        ListNode* nxt=start;
        while(cur!=end){
            nxt =cur->next;
            cur->next=pre;
            pre=cur;
            cur=nxt;
        }
        return pre;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值