数据结构——链表(python)

*链表的相关题目需要分为笔试和面试准备。

*笔记的话可以不用考虑额外的空间复杂度,但是面试的话需要需要提升自己就利用原有的数据的情况下进行题目的解答的过程。

1.链表的基础知识

逻辑结构上能保持数据之间的逻辑顺序,但存储空间不必按照顺序存储。

分类:

单向链表和单向循环链,注意有一个单独的head指针。

2.链表的基本操作

定义一个class Node(object)类似struct 作为基本数据结构,然后再定义class LinkedList(object)。

2.1计算链表长度

        输入头节点,返回长度。self.head就是整个链表的head。

2.2从前插入和从后插入

        从前插入,1)如果插入的数据为空,直接返回。2)如果该链表没有node,直接调整self.head的指向。3)设置该节点为头节点的步骤是,将新增的节点指向原来的第一个节点,再将self.head的节点指向新的节点。

        从后插入,1)如果插入的数据为空,直接返回。2)如果该链表没有没有node直接调整self.head的指向。3)从后插入,设置为尾节点的步骤是定义一个暂时的节点=self.head遍历到最后一个节点(判断条件是node.next=null) 然后将原来最后的节点指向这个新的节点即可。

*注意,传入的都是数字,所有需要在函数中定义一个Node。

2.3查找

见参考python数据结构之链表(linked list)_python linked list_黄小猿的博客-CSDN博客

2.4删除

我只采用一个变量完成这个过程,注意不能用curr_node指向的该node的data与值进行判断,需要将该curr_node.next.data == data进行判断,然后之间将curr.node.next=curr.node.next.next。

注意需要判断1)删除数据是否存在。2)self.head是否为空。3)是否删除的是头节点。

    def deleteAlt(self):
        #只定义一个变量来完成删除操作
        if data is None:
            return 
        if self.head is None:
            return 
        if self.head.data == data:
            self.head = self.head.next
            return
        curr_node = self.head
        while curr_node.next is not None:
            if curr_node.next.data == data:
                curr_node.next = curr_node.next.next
                return
            curr_node = curr_node.next

技能

1.反转链表

该方法在面试的时候可能对减少空间复杂度的作用很大。

整个的思路是我定义两个指针分别一前一后的指向两个节点,

1)先移动next指针到下一个node

2)然后再将当前的节点的next指针指向反转的位置。

3)最后再调整pre和head的指针到相应的位置。

class Solution:
    # 迭代写法
    def ReverseList(self , head: ListNode) -> ListNode:
        # 初始化两个指针pre和next,分别用来前一个节点和当前节点
        pre,next = None,None
        while head:
            # 当前节点指向
            next = head.next
            # 将当前节点指向改为指向前置节点
            head.next = pre
            # 将当前节点作为前置节点
            pre = head
            # 节点向后递归
            head = next
        # 反转链表后,pre节点是头节点
        return pre

2.快慢指针

作用:1.找中间值。2. 删除倒数第n个节点。3. 判断是否为环状链表。

判断一个单链表的回文结构。在只给出head的情况下(不知道长度)。

笔试可以直接将链表里面数据取出来放进额外的空间中(因为链表不能随机访问下表取得位置)

放入栈中,然后一个一个弹出与链表中的值进行一一比对。

然后可以使用快慢指针的方法可以缩短一半空间。

快慢指针就是指定义两个指针,一个走的快(一次走两步)一个走的慢(一次走一步),那么在快指针走到尽头的时候,慢指针就走到中间的位置(分奇数偶数的情况考虑)。

Node和LinkedList的定义如所示 Node和LinkedList链接

题目

141.环形列表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        if not head and not head.next:
            return False
        fast=head.next
        slow=head
        # 如果采用以下代码,可以更加节约
        fast=head.next.next
        slow=head.next
        while fast!= slow:
            if not fast or not fast.next:
                # 不可以指空的空,但是可以指向空,所以只需要判断下一个不为空就可以
                # 因为下一个不为空不为空,那么下一个的下一个就一定存在。
                return False
            fast=fast.next.next
            slow=slow.next
        return True

2.回文链表(快慢指针+栈,快慢指针+反转链表)

 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        '''#快慢指针+栈储存
        if not head.next:
            return True
        fast=head.next
        slow=head
        stack=[]
        stack.append(slow.val)
        while(fast is not None and fast.next is not None):
            fast=fast.next.next
            slow=slow.next
            stack.append(slow.val)
        if(fast is None):
            stack.pop()        
        while(slow.next is not None): #注意判断条件是下一个不为none
            slow=slow.next
            if stack.pop()!=slow.val:
                return False
        return True
        '''
        if not head:
            return True
        fast = slow = head
        while fast.next and fast.next.next:
            fast = fast.next.next
            slow = slow.next      #让慢指针停留在中间靠左边的位置
        pre = None
        cur = slow.next
        slow.next = None          #左右两个链表断开
        while cur:                #反转右半部分的链表
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        #pre指针是右边部分的开头,奇数也不怕
        while pre:       
            if head.val != pre.val:
                return False
            head = head.next
            pre = pre.next
        return True

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lianhuazhi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值