链表问题总结

这篇文章将刷题以来遇到的所有链表类问题做一个总结与回顾:

  1. 题目描述
    输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
    Ying的解法:
    这道题要求的是返回一个链表值的列表,而不是节点列表。因此只需要通过遍历链表,将节点值添加到列表中输出即可。
  • while True:技巧
  • 链表的遍历
    def printListFromTailToHead(self, listNode):
        # write code here
        li = []
        while True:
            if listNode is None:
                break
            else:
                li.append(listNode.val)
                listNode = listNode.next
        li.reverse()
        return li
  1. 题目描述
    输入一个链表,输出该链表中倒数第k个结点。
    Ying的解法:
    这道题要求返回的是倒数第k个节点,一种做法是:遍历一遍,将链表节点一次存入列表中,然后逆序返回第k个;如果要求空间复杂度为O(1),则这种方法不可行,下面这种方法是合适的。
    还有一种方法是维护两个相距k的指针,相当于滑动窗口,当右边的指针到达链表末尾时,前边的指针正好指向的时倒数第k个节点。
  • return 和return None都可以
    def FindKthToTail(self, head, k):
        # write code here
        count = 0
        node = head
        while True:
            if head:
                count+=1
                head = head.next
            else:
                break
        n = count-k+1
        if count
  1. 题目描述
    输入一个链表,反转链表后,输出新链表的表头。
    Ying的解法:
    这道题等价于求反转后的链表,有两种思路:一是通过开辟辅助列表空间,一次遍历后将链表节点添加到列表中,逆序列表,然后遍历列表新建一个链表,时间复杂度O(n),空间复杂度O(n)。二是原地反转,时间复杂度O(n)。
# 方法一:
    def ReverseList(self, pHead):
        # write code here
        li = []
        while True:
            if pHead is None:
                break
            else:
                li.append(pHead.val)
                pHead = pHead.next
        li.reverse()
        t = len(li)
        if t==0:
            return None
        else:
            listNode1 = ListNode(li[0])
            listNode3 = listNode1
            for i in range(1,t):
                listNode2 = ListNode(li[i])
                listNode1.next = listNode2
                listNode1 = listNode2
            return listNode3
# 方法二:
    def ReverseList(self, pHead):
        # write code here
        if not pHead:
            return pHead
        last = None
        while pHead:            
            tmp = pHead.next
            pHead.next = last
            last = pHead
            pHead = tmp
        return last 
  1. 题目描述
    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
    Ying的解法:
    有点归并排序的感觉,时间复杂度O(m+n)
    def Merge(self, pHead1, pHead2):
        # write code here
        s = ListNode(0)
        pHead3= s
        while pHead1 and pHead2:
            if pHead1.val
  1. 题目描述
    输入两个链表,找出它们的第一个公共结点。
    Ying的解法:
    两个单向链表有公共节点,那么从第一个公共节点之后一直是重合的,即'Y'字型。两个链表可能长度不一样,那么先遍历长的,然后从剩下相同长度开始同时遍历,当遇到第一个值相等的节点时,即为找到的第一个公共节点。
  • 链表类问题,头节点往后遍历之前,如果后续还要用到该列表,需要复制一份。
    def FindFirstCommonNode(self, pHead1, pHead2):
        # write code here
        len1 = 0
        len2 = 0
        ppHead1 = pHead1
        ppHead2 = pHead2
        while pHead1:
            len1+=1
            pHead1 = pHead1.next
        while pHead2:
            len2+=1
            pHead2 = pHead2.next
        if len1>len2:
            k = len1-len2
            while k>0:
                ppHead1=ppHead1.next
                k-=1
        else:
            k = len2-len1
            while k>0:
                ppHead2=ppHead2.next
                k-=1
        while ppHead1 and ppHead2:
            if ppHead1.val==ppHead2.val:
                return ppHead1
            else:
                ppHead1 = ppHead1.next
                ppHead2 = ppHead2.next
        return None
  1. 题目描述
    给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
    Ying的解法:
    开辟字典辅助空间,由于是单向链表,所以每个节点都是唯一的。在路径中,只有环的入口节点出现两次。
    def EntryNodeOfLoop(self, pHead):
        # write code here
        dict1 = {}
        dict1[pHead] = 1
        while pHead.next:
            pHead = pHead.next
            if pHead not in dict1:
                dict1[pHead] = 1
            else:
                return pHead
        return None
  1. 题目描述
    在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
    def deleteDuplication(self, pHead):
        # write code here
        if pHead==None or pHead.next==None:
            return pHead
        p=ListNode(None)
        p.next=pHead
        pBefore=p
        pAfter=pHead.next
        while pHead.next!=None:
            flag=False
            while pAfter!=None and pHead.val==pAfter.val:
                if pAfter.next==None:
                    pBefore.next=None
                    return p.next
                pAfter=pAfter.next
                flag=True
            if flag:
                pBefore.next=pAfter
            else:
                pBefore=pHead
            pHead=pAfter
            pAfter=pAfter.next
        return p.next
  1. 两数相加
    给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
    Ying的解法:
    新建一个链表对结果进行存储,因为是逆序的,所以链表遍历的顺序就是加法计算的位数顺序。
  • 考虑到两个链表长度可能不一样,类似归并排序的做法。
  • 同时,最后一个数计算完之后可能有进位,所以作为一种情况考虑。
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        llist = ListNode(0)
        result =llist
        interval = 0
        while l1 and l2:             
            llist.next = ListNode((l1.val+l2.val+interval)%10)
            llist = llist.next
            interval = (l1.val+l2.val+interval)//10
            l1 = l1.next
            l2 = l2.next
                
        while l1:
            llist.next = ListNode((l1.val+interval)%10)
            llist = llist.next
            interval = (l1.val+interval)//10
            l1 = l1.next
        
        while l2:
            llist.next = ListNode((l2.val+interval)%10)
            llist = llist.next
            interval = (l2.val+interval)//10
            l2 = l2.next
        
        if interval!=0:
            llist.next = ListNode(interval) 
        return result.next

== 待补充==

你可能感兴趣的:(链表问题总结)