• 翻转链表-迭代和递归双版本


    将一个链表翻转,如 1->2->3->4 变成 4->3->2->1 的链表。这是一个非常著名的面试题,看似非常的简单,但实际上非常的tricky.

    实现方法可以有递归和迭代两种方法,这两个算法也都保证了in-place 和 one-pass. 所以效率还是很高的。这篇文章主要基于http://leetcode.com/2010/04/reversing-linked-list-iteratively-and.html. 他讲解的基本已经比较清楚,我就再从比较菜的角度去分析一下。

    迭代方法:

    首先来看迭代版本的基本思路,先上图:

    上图就是迭代的第一步,基本就是prev, curr, next三个指针跟踪着当前点的情况,然后更新后向前移动,直到移到链表末尾

    看代码后应该更清晰:

     1 void reverse(Node*& head) {
     2   if (!head) return;
     3   Node* prev = NULL;
     4   Node* curr = head;
     5   while (curr) {
     6     Node* next = curr->next;
     7     curr->next = prev;
     8     prev = curr;
     9     curr = next;
    10   }
    11   head = prev;
    12 }

    代码中要注意 Node*&, 毕竟是改变了链表的结构,所以链表的头指针应该传一个引用。

    翻转链表的迭代版本很清晰,且容易实现。而下面的递归方法虽然代码很短,但是比较难理解,且实现起来细节也很多。

    递归版本:

    这个整体过程比较复杂,所以还是先上图:

    然后来看着代码分析:

    void reverse(Node*& p) {
      if (!p) return;
      Node* rest = p->next;
      if (!rest) return;
      reverse(rest);
      p->next->next = p;
      p->next = NULL;
      p = rest;
    }

    递归过程中,首先迅速由递归函数进行至第一幅图的情况(其实下面还有一步,此时rest 指向NULL,返回到第一幅的情况)

    然后将当前节点的下一节点的子节点倒指向其父节点(即当前节点),然后将当前节点指向NULL,即当前我们翻转了从当前节点到末尾节点。

    注意这之后的最后一个语句,将p 赋值为 rest,然后返回。 返回到上一层会发生什么呢? 这就要注意每层调用reverse函数时,传进去的指针式rest, 即修改上一层的rest指针为当前层的rest指针,换句话说,在以后递归的过程中,rest指针将一直指向最后一个节点,即新的链表根节点。

  • 相关阅读:
    drfViewSet (指定get关联的函数) 第一波
    drfViewSet之路由简写的方法
    defAPIView 响应 和 接收
    GenericAPIView
    Django接收前端传过来数组的方法
    Django数据迁移失败问题记录 managed = False不知道是不是不迁移的意思有空试试
    Minin混合类
    基于apiview接口实现 查、更新、删除
    drf序列化和反序列化。查询和提交 之Serializer
    python之jsonpath
  • 原文地址:https://www.cnblogs.com/soyscut/p/3801539.html
Copyright © 2020-2023  润新知