Python程序员面试算法宝典——学习笔记(一)

本文是Python程序员面试算法学习笔记的第一部分,主要探讨单链表的逆序问题。介绍了三种方法实现链表逆序:就地逆序、递归法和插入法,详细阐述了每种方法的思路、时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

第一章 链表

1.1如何实现链表的逆序

题目描述:给定一个带头结点的单链表,请将其逆序。如果单链表原来为head->1->2->3->4->5->6->7,那么逆序后为head->7->6->5->4->3->2->1

方法一:就地逆序

在遍历链表时,修改当前结点的指针方向,让它指向前驱结点。为此定义一个指针变量来保存前驱结点的地址;除此之外,为了能找到后继结点,还需定义一个指针变量保存后继结点的地址,当所有的结点保存好以后就可以完成逆序了。
pre:表示前驱结点
cur:表示当前结点
next:表示后继结点

head
pre
cur
next
##################################
#链表的数据结构#
##################################
class LNode:
      def __init__(self,x):
          self.data = x     #数据域
          self.next = None  #指针域
#################################
#具体代码实现
#################################

def Reverse(head):
    #判断链表是否为空
    if head == None or head.next == None:
          return
    pre = None    #前驱结点
    cur = None    #当前结点
    next = None   #后继结点
    #把链表首结点变为尾结点
    cur = head.next  #把头结点的下一个结点作为当前结点
    next = cur.next  #当前结点的下一结点作为后继结点
    cur.next = None  #将后继结点的指针赋给空值
    pre = cur        #将结点后移,原来的当前结点作为现在的前驱结点
    cur = next       #将原来的后继结点作为现在的当前结点
    #使当前遍历到的结点cur指向其前驱结点
    while cur.next != None:  #当遍历到尾结点时就退出循环
        next = cur.next      #记录当前结点的后继结点
        cur.next = pre       #当前结点指向前驱结点
        pre = cur            #并将原来的当前结点作为现在的前驱结点
        cur = cur.next       #遍历下一结点
        cur = next           #并将原来的后继结点作为当前结点
        #链表最后一个结点指向倒数第二个结点
        cur.next = pre
        #链表的头结点指向原来链表的尾结点
        head.next = cur

if __name__ == "__main__":
     i = 1
     #链表头结点
     head = LNode()
     head.next = None
     tmp = None
     cur = head
     
     #构造单链表
     while i<8:
     tmp = LNode()
     tmp.data = i
     tmp.next = None
     cur.next = tmp
     cur = tmp
     i += 1
     print("逆序前:")
     cur = head.nex
     t
     while cur != None:
         print(cur.data)
         cur = cur.next
     print("\n  逆序后:")
     Reverse(head)
     cur = head.next
     while cur != None:
         print(cur.data)
         cur = cur.next

时间复杂度:O(N)
空间复杂度:O(1)

方法二:递归法

先逆序除第一个结点以外的子链表(将1->2->3->4->5->6->7变为1->7->6->5->4->3->2),接着将结点1添加到逆序的子链表后面(1->7->6->5->4->3->2变为7->6->5->4->3->2->1)

####################################
#具体代码实现
####################################
#不带头结点的链表
def RecursiveReverse(head):
    #如果链表为空或只有一个元素
    if head is None or head.next is None:
        return head
    else:
        #反转后面的结点
        newhead = RecursionReverse(head.next)
        #把当前遍历的结点加到后面结点逆序后链表的尾部
        head.next.next = head
        head.next = None
     return newhead
#带头结点的链表
def Reverse(head):
    if head is None:
        return 
    #获取链表的第一个结点
    firstNode = head.next
    #对链表进行逆序
    newhead = RecursiveReverse(firstNode)
    #头结点指向逆序后的第一个结点
    head.next = newhead
    return newhead

时间复杂度:O(N)
空间复杂度:O(N)

方法三:插入法

从链表的第二个结点开始,把遍历到的结点插入到头结点的后面,直至遍历结束。例如原链表为head->1->2->3->4->5->6->7,在遍历到2时,将其插入头结点后,链表变为
head->2->1->3->4->5->6->7,同理将后序遍历到的结点都插入head后。

########################################
#具体代码实现
########################################
def Reverse(head):
    #判断链表是否为空
    if head is None or head.next is None:
        return
    cur = None  #当前结点
    next = None #后继结点
    cur = head.next.next
    #设置链表第一个结点为尾结点
    head.next.next = None
    #把遍历到结点插入头结点后面
    while cur is not None:
        next = cur.next
        cur.next = head.next
        head.next = cur
        cur = next    

时间复杂度:O(N)
空间复杂度:O(1)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值