[编程题]反转链表
时间限制:1秒 空间限制:32768K
输入一个链表,反转链表后,输出链表的所有元素。
解法一.循环反转链表(非递归法)
整体思路就是,从原链表的头部一个一个取节点并插入到新链表的头部
p始终指向要反转的结点
newHead 指向反转后的首结点
每反转一个结点,把p结点的next指向newHead, newHead再移动到P的位置成为反转后首结点, 再把p通过tmp保存的位置向后移动一个结点直至None结束
- 首先对于链表设置两个指针:
- 然后依次将旧链表上每一项添加在新链表的后面,然后新链表的头指针newhead移向新的链表头,如下图所示。此处需要注意,不可以上来立即将上图中P->next直接指向newhead,这样存放2的地址就会被丢弃,后续链表保存的数据也随之无法访问。而是应该设置一个临时指针tmp,先暂时指向P->next指向的地址空间,保存原链表后续数据,然后再让P->next指向newhead,
最后P=tmp就可以取回原链表的数据了,所有循环访问也可以继续展开下去。
进行下一次迭代,指针继续向后移动,直到P指针指向NULL停止迭代。
C++
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode* newhead = NULL;
ListNode* p = pHead;
if(p==NULL || p->next==NULL) return p;
else{
while(p){ //一直迭代到链尾
ListNode* tmp = p->next;//暂存p下一个地址,防止变化指针指向后找不到后续的数
p-> next = newhead; //p->next指向前一个空间
newhead = p; //新链表的头移动到p,扩长一步链表
p= tmp; //p指向原始链表p指向的下一个空间
}
return newhead;
}
}
};
python解法
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if not pHead or not pHead.next:
return pHead
newHead = None
while pHead:
tmp = pHead.next
pHead.next = newHead
newHead = pHead
pHead = tmp
return newHead
2.递归法
递归的方法其实是非常巧的,它利用递归走到链表的末端,然后再更新每一个node的next 值 ,实现链表的反转。而newhead 的值没有发生改变,为该链表的最后一个结点,所以,反转后,我们可以得到新链表的head。
注意关于链表问题的常见注意点的思考:
1、如果输入的头结点是 NULL,或者整个链表只有一个结点的时候
2、链表断裂的考虑
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
//递归方式
ListNode * ReverseList(ListNode * phead){
//如果链表为空或者链表中只有一个元素
ListNode* p = phead;
if(p==NULL || p->next==NULL)
return p;
else{
ListNode * newhead=ReverseList(p->next);//先反转后面的链表
p->next->next=p;//再将当前节点设置为其然来后面节点的后续节点
p->next=NULL;
return newhead;
}
}
};
python
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
if not pHead or not pHead.next :
return pHead
tmp=pHead.next
pHead.next=None
res=self.ReverseList(tmp)
tmp.next=pHead
return res
由此对于该问题我们知道迭代是从前往后依次处理,直到循环到链尾;而递归恰恰相反,首先一直迭代到链尾也就是递归基判断的准则,然后再逐层返回处理到开头。
总结来说,链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头。