《剑指Offer》——链表(Python3 实现)

目录

链表

1、从尾到头打印链表

2、链表中倒数第K个结点

3、反转链表

4、合并两个排序的链表

5、复杂链表的复制

6、两个链表的第一个公共结点

7、链表中环的入口点

8、删除链表中重复的结点


链表

1、从尾到头打印链表

问题:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

思路:直接遍历一遍链表保存结果到list中,再返回倒序的list即可。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        arr=[]
        while listNode:
            arr.append(listNode.val)
            listNode=listNode.next
        return arr[::-1]

2、链表中倒数第K个结点

问题:输入一个链表,输出该链表中倒数第K个结点。

思路:先计算链表的长度,然后计算找到倒数第k个需要几次循环,并判其中关系。最后,用for循环,不断将指针指向下一个节点,即为所求。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def FindKthToTail(self,head,k):
        len_node=0
        temp=head
        while temp:
            temp=temp.next
            len_node+=1
        run_times=len_node-k
        if run_times<0 or k<0:
            return
        for i in range(run_times):
            head=head.next
        return head

3、反转链表

问题:输入一个链表,反转链表后,输出链表的所有元素。

思路:利用三个指针逐个翻转(头插法建立单链表)。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def ReverseList(self,phead):
        if not phead:
            return
        p=phead
        q=phead.next
        p.next=None
        while q:
            r=q.next
            q.next=p
            p=q
            q=r
        return p 

4、合并两个排序的链表

问题:输入两个单调递增的链表,输出两个链表合成后的链表,需要合成后的链表满足单调不减规则。

思路一:迭代方法求解。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def Merge(self,pHead1,pHead2):
        p1=pHead1
        p2=pHead2
        if p1 and p2:   #首先,判断哪个链表的头结点的值小,将值小的作为合并后链表的头结点
            if p1.val<=p2.val:
                head=p1
                p1=p1.next
            else:
                head=p2
                p2=p2.next
            r = head
        elif p1:
            return p1
        else:
            return p2
        while p1 and p2:
            if p1.val<=p2.val:
                r.next=p1
                p1=p1.next
                r=r.next
            else:
                r.next=p2
                p2=p2.next
                r=r.next
        if p1:
            r.next=p1
        if p2:
            r.next=p2
        return head

思路二:递归方法。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def Merge(self,pHead1,pHead2):
        merged=None
        if not pHead1:   #当pHead1为空时,返回pHead2
            return pHead2
        if not pHead2:   #当pHead2为空时,返回pHead1
            return pHead1
        #第一个链表中的第一个点小于第二个链表中的第二个点,那么merged第一个点就是pHead1的第一个点
        #对于它的next,继续执行递归
        if pHead1.val<=pHead2.val:
            merged=pHead1
            pHead1=pHead1.next
            merged.next=self.Merge(pHead1,pHead2)
        else:
            merged=pHead2
            pHead2=pHead2.next
            merged.next=self.Merge(pHead1,pHead2)
        return merged

5、复杂链表的复制

问题:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

# -*- coding:utf-8 -*-
class RandomListNode:
    def __init__(self, x):
        self.label =x
        self.next =None
        self.random=None
class Solution:
    def Clone(self,pHead):
        if not pHead:
            return pHead
        #开辟一个新结点
        copy=RandomListNode(pHead.label)
        copy.next=pHead.next
        copy.random=pHead.random
        #递归剩余的结点
        copy.next=self.Clone(pHead.next)
        return copy

6、两个链表的第一个公共结点

问题:输入两个链表,找出它们的第一个公共结点。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None
class Solution:
    def FindFirstCommonNode(self,pHead1,pHead2):
        if not pHead1 or not pHead2:
            return None
        length1=0
        length2=0
        p1=pHead1
        p2=pHead2
        #分别计算两个链表的长度
        while p1:
            length1+=1
            p1=p1.next
        while p2:
            length2+=1
            p2=p2.next
        #根据两个链表的长度,确定长、短链表和它们之间的长度差
        if length1>=length2:
            step=length1-length2
            longList=pHead1
            shortList=pHead2
        else:
            step=length2-length1
            longList=pHead2
            shortList=pHead1
        #让长链表先走step步
        for i in range(step):
            longList=longList.next
        #同时遍历两个链表,让他们不断指向next,并判断何时相等,相等时返回任一一个链表即可
        while longList and shortList:
            if longList==shortList:
                return longList
            else:
                longList=longList.next
                shortList=shortList.next
        return None

7、链表中环的入口点

问题:一个链表中包含环,请找出该链表的环的入口点。

思路:第一步,找环中相汇点。分别用p,q指向链表头部,p每次走两步,q每次走一步,直到p==q找到在环中的相汇点。

第二步,找环的入口。接上一步,当p==q时,p所经过的节点数为2x,q所经过的节点数为x,设环中有n个节点,p比q多走一个环,有2x=x+n;n=x;可以看出q实际走了一个环的步数,再让p指向链表头部,q位置不变,p,q每次走一步直到p==q;此时p,q指向环的入口。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None
class Solution:
    def EntryNodeOfLoop(self,pHead):
        if pHead==None:
            return None
        if pHead.next==None or pHead.next.next==None:
            return None
        #使用快慢指针,p每次走两步,q每次走一步
        p=pHead.next.next
        q=pHead.next
        #第一次循环,直到p和q相遇,p每次走两步,q每次走一步
        while p!=q:
            p=p.next.next
            q=q.next
            if p.next==None or p.next.next==None:
                return None
        #第二次循环,直到p和q相遇,让快指针p回到开始的点,p和q每次都走一步
        p=pHead
        while p!=q:
            p=p.next
            q=q.next
        return p

8、删除链表中重复的结点

问题:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。例如,链表1->2->3->3->4->4->5处理后为1->2->5。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None
class Solution:
    def deleteDuplication(self,pHead):
        temp=[]
        head=pHead
        #先将pHead中所有结点的value全部放到temp列表中去
        while head:
            temp.append(head.val)
            head=head.next
        result=ListNode(0)  #创建一个新的指针
        head=result   #让head指向这个指针
        for i in temp:
            if temp.count(i)==1:  #对于temp中的元素,如果出现次数等于1就添加到head的next指针
                head.next=ListNode(i)
                head=head.next
        return result.next

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页