美文网首页
python 实现链表常见算法

python 实现链表常见算法

作者: clshinem | 来源:发表于2017-09-19 19:47 被阅读0次

    之前在刷算法题的时候,见过很多基础的链表的操作,本着整理一下的想法,在这儿总结一下(PS。每次写都会遇到多多少少的问题·······我真的太菜了

    1:先来实现一个链表节点
    class ListNode():
        def __init__(self,num):
            self.val = num
            self.next = None
    
    2:在O(1)时间删除一个链表节点

    这个的主要耗费在找到这个节点的前一个节点,所以采用不删除这个节点,而是把后一个节点的值赋给这个节点,然后删除这个节点之后的节点。需要考虑如果这个节点是链表的尾节点那么就需要从头遍历这个链表了,代码如下

    def deleteNode(self,pHead,Node):
            if Node == None or pHead == None:
                return
            if Node.next != None:
                Node.val = Node.next.val
                Node.next = Node.next.next
            elif Node == pHead:# 如果链表只有一个节点,那么就把头节点删掉就好了
                pHead.val = None
            else:
                pNode = pHead
                while pNode.next != Node:
                    pNode = pNode.next
                pNode.next = None
            
            return pHead
    
    3:链表的倒数第K个节点

    首先我们可以遍历这个链表放进list中,然后采用list 的切片方法来取到后面的倒数第k个数,但是算法的意义不大
    只需要遍历一遍的做法,两个指针,一个先走k-1步,另一个再走

    # -*- coding:utf-8 -*-
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    class Solution:
        # 返回ListNode
        def ReverseList(self, pHead):
            pnode = pHead
            preverseHead = None
            ppre = None
            while pnode!= None:
                pnext = pnode.next
                if pnext == None:
                    preverseHead = pnode
                pnode.next=ppre
                ppre=pnode
                pnode = pnext
            return preverseHead
            # write code here
    
    4:链表的中间节点

    这个的思想大致也就是一个一次走两步,一个一次走一步,当快的走的最后的时候,慢的在中间

    def midoflist(self,pHead):
            fast,slow = pHead,pHead
            while fast and fast.next: 
            #这个条件很重要,如果设置为fast.next的话会出现Nonetype没有next这个错误。
            #fast 在前,如果fast已经为None,那么,fast.next也一定不存在   
                fast=fast.next.next
                slow=slow.next
            print slow.val
    
    5:判断两个链表相交和相交的第一个节点
    这个代码不写了,两种办法,第一种,一个链表的尾节点指向另一个链表的头节点,这样判断两个链表相交等同于判断链表是否有环
    而两个链表相交的第一个节点,那就是先找到两个链表的长度,然后一个指针先走L长 - L短 然后一个走的最后另一个就是相交的第一个节点
    还有就是同判断相交一样,连城环然后找环的入口
    
    6:判断是否有环

    这个就是一个快指针,一个慢,慢的总会追上快的(据说百度面试很喜欢问慢的为什么会追上快的,这个明天有空在写一下)

    def cricle(self,pHead):
            fast,slow = pHead,pHead
            while fast and fast.next:
                fast=fast.next.next
                slow = slow.next
                if (fast == slow):
                    print "youhuan"
                    return
            print "meiyou"
            return
    
    7:找环的入口

    改天补个图
    这个思想是,一个从相交的地方走,一个从头走,当相遇的时候,这个相遇的节点就是入口,代码如下

    def circlestart(self,pHead):
            fast,slow = pHead,pHead
            while fast and fast.next:
                fast = fast.next.next
                slow = slow.next
                if (fast == slow):
                    break
            slow = pHead
            while fast !=slow:
                fast=fast.next
                slow=slow.next
            print fast.val
            return fast
    

    ps:突然发现粘上来的代码,缩进有些问题,改一下缩进再用
    下面附上自己测试用的代码,写的非常菜

    node1 = ListNode(1)
    node2 = ListNode(2)
    node3 = ListNode(3)
    node4 = ListNode(4)
    node5 = ListNode(5)
    node6 = ListNode(6)
    
    node1.next = node2
    node2.next = node3
    node3.next = node4
    node4.next = node5
    node5.next = node6
    node6.next = node3      
    
    s = solution()
    # s.deleteNode(node1,node1)
    s.circlestart(node1)
    

    再ps:这次想通了如何构造一个有环的链表哈哈,算难得的长进吧嘿嘿


    image.png

    相关文章

      网友评论

          本文标题:python 实现链表常见算法

          本文链接:https://www.haomeiwen.com/subject/ehsgsxtx.html