刷题01-单向链表反转

单向链表反转(迭代+递归)

之前刷题目的时候有刷到过,直接用了暴力,迭代的两种方法过了,就懒得看递归的方法了。结果在深圳场的平安普惠技术面试的时候,面试官正好问到这个题目,用迭代法回答了思路,又问有没有递归的思路,悔不当初啊!

题目描述: 输入一个链表,反转链表后,输出新链表的表头

  1. 暴力构造法: 链表内每一个节点都是一个简易的数据,直接用vector<ListNode*>将所有节点数据存储下来,利用vector的先进后出特性,重新构建一个新的链表,既是反转过后的链表。
    时间复杂度:O(n),空间复杂度:O(n)

根据上述分析,得到下面的代码:

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        vector<ListNode*> pv;
        ListNode* p=pHead;
        while(p){
            pv.push_back(p);
            p=p->next;
        }
        ListNode* NewpHead=NULL;
        p=NewpHead;
        while(!pv.empty()){
            p=pv.back();
            pv.pop_back();
            p=p->next;
        }
        return NewpHead;
    }
};
  1. 迭代翻转法: 链表节点的结构中next指针指向下一个节点,要想反转链表,即改变每个节点的next指针指向
    需要三个额外的指针来保存原始链表和反转链表的结构:
    front指针 指向当前需要调整next指针的节点
    tile指针 指向NULL,是反转过后的链表的头节点
    save指针 指向原始链表中待反转的第一个节点
    每次迭代过程如图所示:
    在这里插入图片描述
    时间复杂度:O(n),空间复杂度O(1)
    需要进行n次迭代,每次迭代中需要的时间是常数级别O(1),整个过程只需要三个额外的ListNode指针空间,也是常数级别O(1)。

根据上述分析,得到下面的代码:

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(!pHead)
            return NULL;
        ListNode* front=pHead;
        ListNode* tile=NULL;
        ListNode* save=NULL;
       
        while(front){
            save=front->next;
            front->next=tile;
            tile=front;
            front=save;
        }
        
        return tile;
    }
};
  1. 递归翻转法: 递归法的两个基本要素:边界条件,递归模式,必须清晰明了。
    边界条件: 反转单向链表的边界条件是当前节点已经为链表最末尾的节点,即
    node->next==NULL
    递归模式: 最重要的就是把大的问题变小化。如只考虑两个节点的反转,n1->n2->NULL,这时递归函数只要做两个事情:
    a、n1->next->next=n1;
    b、n1->next=NULL;

    这样子就完成了两个节点的反转,得到链表n2->n1->NULL。
    那么递归模式应该返回什么呢?
    在n1->n2->n3->NULL链表中,经过最后两个节点的反转,变成
    在这里插入图片描述
    因此,每次反转过后,返回的应该是原始链表的最末尾节点(n3)。
    时间复杂度:O(n),空间复杂度:O(n)
    n个节点的链表,要递归n次;每次递归模式内,需要时间为常数级别,时间为O(1),都要创建O(1)的newpHead空间。

根据上述分析,得到下面的代码:

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(!pHead || pHead->next==NULL)
            return pHead;
        
        ListNode* newpHead=ReverseList(pHead->next);
        pHead->next->next=pHead;
        pHead->next=NULL;
        
        return newpHead;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值