python链表题目及代码leetcode和剑指offer

本文详细探讨了Python链表的各种操作,包括从尾到头的顺序返回链表值、找到倒数第k个节点、合并单调递增链表、反转链表、判断链表环、寻找链表交点、复制带有随机指针的链表以及链表分区等。并提供了LeetCode和剑指Offer的相关题目及解题代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简单操作
1、输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

class Solution:
    def printListFromTailToHead(self, listNode):
        res=[]
        while listNode:
            res.insert(0,listNode.val)
            listNode=listNode.next
        return res

准备工作:输出一个链表,怎么码代码?输出链表1->2->3

class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None

def PrintChain(node):
    while node:
        print node.val
        node=node.next
        
l1=ListNode(1)
l2=ListNode(2)
l3=ListNode(3)
l1.next=l2
l2.next=l3
PrintChain(l1)

2、输入一个链表,输出该链表中倒数第k个结点。

class Solution:
    def FindKthToTail(self,head,k):
        firstPoint=head
        secondPoint=head
        for i in range(k):
            if firstPoint==None:
               return None 
            firstPoint=firstPoint.next
        while firstPoint!=None:
            firstPoint=firstPoint.next
            secondPoint=secondPoint.next
        return secondPoint

3、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

class Solution:
    def Merge(self, pHead1, pHead2):
        if pHead1==None:
            return pHead2
        elif pHead2==None:
            return pHead1
        if pHead1.val<pHead2.val:
            newHead=pHead1
            pHead1=pHead1.next
        else:
            newHead=pHead2
            pHead2=pHead2.next
        newHead.next=self.Merge(pHead1,pHead2)
        return newHead

二、反转链表(或反转其中一部分)与其应用
反转链表;leetcode206. Reverse Linked List

class Solution:
    def ReverseList(self, pHead):
        pTmp = pHead
        newHead = None
        while pTmp:
            pTmp1 = pTmp.next
            pTmp.next = newHead
            newHead = pTmp
            pTmp = pTmp1
        return newHead

或,思想一样

class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        if pHead == None:
            return None
        pTmp = pHead
        pTmp1 = pHead.next
        newHead = None
        while pTmp:
            pTmp.next = newHead
            newHead = pTmp
            pTmp = pTmp1
            if pTmp1:
                pTmp1 = pTmp1.next
        return newHead

leetcode92. Reverse Linked List II对链表中一部分进行反向

class Solution:
    def reverseBetween(self, head, m, n):
        dummy = ListNode(0)   #重点:必须加一个虚拟的指针
        dummy.next = head
        p1 = dummy
        for i in range(m-1):
            p1 = p1.next
        p2 = p1.next
        newhead = None
        for i in range(n-m+1): #反转m到n链表
            p3 = p2.next
            p2.next = newhead
            newhead = p2
            p2 = p3
        p1.next.next = p2
        p1.next = newhead
        return newhead if p1 == dummy else head

letcode25. Reverse Nodes in k-Group

class Solution:
    def reverseKGroup(self, head, k):
        i = 0
        p = head
        p1 = head
        while p and i<k:
            p = p.next
            i += 1
        if i < k:     #判断够不够k个
            return head
        pre = self.reverseKGroup(p,k) #若够k则处理下一段
        for i in range(k):  #对这一段进行翻转
            p2 = p1.next
            p1.next = pre
            pre = p1
            p1 = p2
        return pre

leetcode234. Palindrome Linked List 1->2->2->1 True

#先用快慢指针找到中间位置,若不要求空间O(1),则可用栈依次放入前半截元素,再一一取出与
#后边链中元素比对;要求空间O(1):将后半截链表反转,再与前半截一一比对
class Solution:
    def isPalindrome(self, head):
        fastp = slowp = head   #快慢指针找中间位置
        while fastp and fastp.next and slowp:
            fastp = fastp.next.next
            slowp = slowp.next
        newhead = None
        while slowp:   #反转后半截链表,设置新表头newhead
            p1 = slowp.next
            slowp.next = newhead
            newhead = slowp
            slowp = p1
        while newhead and head.val == newhead.val:   #一一比对
            head = head.next
            newhead = newhead.next
        if newhead == None:
            return True
        else:
            return False

三、判断链表里是否有环
leetcode141. Linked List Cycle判断是否有环

class Solution(object):
    def hasCycle(self, head):
        fastp = slowp = head
        while fastp and fastp.next:
            fastp = fastp.next.next
            slowp = slowp.next
            if fastp == slowp:
                return True
        return False

leetcode142. Linked List Cycle II,剑指offer链表中环的入口节点:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

#设从起点到环的起点长度为a,从环的起点到第一次相遇长度为b,圈长为n
# 根据2*(a+b)=a+b+k*n,得a+b=k*n。所以本题用快慢指针,待第一次相遇
#再重置慢指针到起点,两个指针同步走,再次相聚即是环的入口,因为a+b是
# n的整数倍
class Solution(object):
    def detectCycle(self, head):
        fastp = slowp = head
        while fastp and fastp.next:
            fastp = fastp.next.next
            slowp = slowp.next
            if fastp == slowp:
                slowp = head
                break
        if fastp == None or fastp.next == None:
            return None
        else:
            while slowp != fastp:
                fastp = fastp.next
                slowp = slowp.next
            return slowp

class Solution:
    def EntryNodeOfLoop(self, pHead):
        fastp = slowp = pHead
        while fastp and fastp.next:
            fastp = fastp.next.next
            slowp = slowp.next
            if fastp == slowp:
                slowp = pHead
                break
        if fastp == None or fastp.next == None:
            return None
        else:
            while slowp != fastp:
                fastp = fastp.next
                slowp = slowp.next
            return slowp

四、单向链表找交点
160. Intersection of Two Linked Lists输入两个链表,找出它们的第一个公共结点。
法一:

#将长的链先往后next,直到两个链长度相等,再同时next,直到两个相等
class Solution(object):
    def getIntersectionNode(self, headA, headB):
        lenA = lenB = 0   #先得A链长度lenA和B链长度lenB
        pA = headA
        pB = headB
        while pA:  
            pA = pA.next
            lenA += 1
        while pB:
            pB = pB.next
            lenB += 1
        pA = headA
        pB = headB
        while lenA > lenB:   #将长链next直到两链相等
            pA = pA.next
            lenA -= 1
        while lenB > lenA:
            pB = pB.next
            lenB -= 1

        while pA != pB:
            pA = pA.next
            pB = pB.next
        return pA

以下是剑指offer相应题目代码

class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        pTmp1=pHead1
        pTmp2 = pHead2
        while pTmp1 and pTmp2:
            pTmp1=pTmp1.next
            pTmp2=pTmp2.next
        if pTmp1:
            k = 0
            while pTmp1:
                pTmp1 = pTmp1.next
                k += 1
            pTmp1=pHead1
            pTmp2=pHead2
            for i in range(k):
                pTmp1=pTmp1.next
        else:
            k=0
            while pTmp2:
                pTmp2 = pTmp2.next
                k += 1
            pTmp2=pHead2
            pTmp1=pHead1
            for i in range(k):
                pTmp2=pTmp2.next
        
        while pTmp1 != pTmp2:
            pTmp1=pTmp1.next
            pTmp2=pTmp2.next
        return pTmp1

法二:通过调用函数,将两种情况调用

class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        pTmp1 = pHead1
        pTmp2 = pHead2
        while pTmp1 and pTmp2:
            pTmp1 = pTmp1.next
            pTmp2 = pTmp2.next
            
        def findequal(longchain,shortchain, longhead, shorthead):
            k=0
            while longchain:
                longchain=longchain.next
                k += 1
                
            longchain = longhead
            shortchain = shorthead
            for i in range(k):
                longchain=longchain.next
                
            while longchain != shortchain:
                longchain=longchain.next
                shortchain=shortchain.next
            return longchain
        if pTmp1:
            return findequal(pTmp1,pTmp2,pHead1,pHead2)
        else:
            return findequal(pTmp2,pTmp1,pHead2,pHead1)

五、复值random指针
leetcode138. Copy List with Random Pointer

class Solution(object):
    def copyRandomList(self, head):
        if head == None:
            return None
        p = head
        while p:  #复值每一个节点加到原节点后面
            node = Node(p.val, p.next, p.random)
            node.next = p.next
            p.next = node
            p = node.next
        p = head
        while p: #将random指针复值
            if p.random:
                p.next.random = p.random.next
            p = p.next.next
        p = head
        newhead = p.next
        p1 = newhead
        while p and p1.next:   #将两条链断开
            p.next = p1.next
            p = p.next
            p1.next = p.next
            p1 = p1.next
        p.next = None
        p1.next = None
        return newhead

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

import copy
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        # write code here
        ret=copy.deepcopy(pHead)
        return ret

方法二:

class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        # write code here
        if pHead == None:
            return None
        pTmp = pHead
        while pTmp:
            node = RandomListNode(pTmp.label)
            node.next = pTmp.next
            pTmp.next = node
            pTmp = node.next

        pTmp = pHead
        while pTmp:
            if pTmp.random:
                pTmp.next.random = pTmp.random.next
            pTmp = pTmp.next.next

        pTmp = pHead
        pTmp1 = pHead.next
        newhead = pHead.next
        while pTmp:
            pTmp.next = pTmp.next.next
            pTmp=pTmp.next
            if pTmp1.next:
                pTmp1.next = pTmp1.next.next
            pTmp1=pTmp1.next
        return newhead

注:若想在pycharm调试则需加

if __name__ == "__main__":
    n1=RandomListNode(1)
    n2 = RandomListNode(2)
    n3 = RandomListNode(3)
    n4 = RandomListNode(4)
    n1.next = n2
    n2.next = n3
    n3.next = n4
    s=Solution()
    newhead = s.Clone(n1)
    tmp = newhead
    while tmp:
        print tmp.label
        tmp = tmp.next

**六、链表partition **
leetcode86. Partition List:链表里存放整数,给定x,把比x小的节点放到>=x之前

#思路:建立两个虚拟表头,比x小的放到leftp后边,其他放到rightp后边,最后连到一起
class Solution:
    def partition(self, head, x):
        dummyleft = ListNode(0)
        dummyright = ListNode(0)
        leftp = dummyleft
        rightp = dummyright
        p = head
        while p:
            if p.val < x:
                leftp.next = p
                leftp = leftp.next
            else:
                rightp.next = p
                rightp = rightp.next
            p = p.next
        rightp.next = None
        leftp.next = dummyright.next
        return dummyleft.next 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值