算法题-反转单链表

40 篇文章 0 订阅
38 篇文章 0 订阅

[编程题]反转链表

时间限制: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

由此对于该问题我们知道迭代是从前往后依次处理,直到循环到链尾;而递归恰恰相反,首先一直迭代到链尾也就是递归基判断的准则,然后再逐层返回处理到开头。
总结来说,链表翻转操作的顺序对于迭代来说是从链头往链尾,而对于递归是从链尾往链头。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值