zoukankan      html  css  js  c++  java
  • 链表问题整理

    1.单链表操作

    class ListNode:
        def __init__(self,data):
            #data为数据项,next指向下一节点
            self.data = data
            self.next = None
    
    class LinkList:
        def __init__(self):
            #初始化head指针
            self.head = None
    
        #创建链表
        def initList(self,data):
            self.head = ListNode(data[0])
            cur = self.head
            for val in data[1:]:
                node = ListNode(val)
                cur.next = node
                cur = cur.next
            return self.head
    
        #打印链表
        def printList(self):
            if self.head == None:return
            cur = self.head
            while cur:
                print(cur.data,'->',end='')
                cur = cur.next
    
        #查找某元素
        def findKth(self,e):
            temp = self.head
            while temp:
                if temp.data == e:
                    return temp
                temp = temp.next
            return None
    
        #将元素element插入到e元素后
        def insertK(self,e,element):
            Node = ListNode(element)
            p = self.findKth(e)
            if p == None:return
            temp = p.next
            p.next = Node
            Node.next = temp
            return self.head
    
        #删除某元素
        def remove(self,e):
            cur = self.head
            pre = None
            while cur:
                if cur.data == e: #找到了指定元素
                    if not pre: #如果为头结点
                        self.head = cur.next
                    else:
                        pre.next = cur.next
                    break
                else:
                    pre = cur
                    cur = cur.next

    2.链表反转

    2.1 反转一个单链表

    力扣206题:https://leetcode-cn.com/problems/reverse-linked-list/

        def reverselist(self,head):
            #递归结束的条件
            if head == None or head.next == None:
                return head
            p = self.reverselist(head.next)
            head.next.next = head
            head.next = None
            return p


    在链表的题型中,一定要注意的是各个指针所指向的链表中的位置,函数一般返回的都是头节点。一般只要搞清楚指针的具体指向以及在函数中的变化,链表问题一般都能看懂。

    head 指向 1,在递归后,头节点后的链表实现了反转,这时 p 指针指向原链表中的最后一个节点,也即是 4。根据图示,接下来要做的就是将位节点2(head.next)的下一个指针指向 节点1 (head),并将原链表的头节点指向None,因此需要head.next.next = head,以及head.next = None。接下来需要返回结果链表的头节点,也即是p即可。

    非递归:

        def reverselist(self,head):
            pre = None
            cur = head
            while cur:
                p = cur.next
                cur.next = pre
                pre = cur
                cur = p
            return pre

    2.2 反转链表前N个节点

        #递归
        def reverseN(self, head, n):
            if n == 1:
                return head 
            p = self.reverseN(head.next, n-1)
            successor = head.next.next
            head.next.next = head
            head.next = successor
            return p
    
        #非递归
        def reverseN(self, head, n):
            if n == 1:
                return head
            pre = None
            cur = head 
            count = 0
            while count != n:
                p = cur.next
                cur.next = pre 
                pre = cur
                cur = p 
                count += 1
            head.next = p
            return pre 

    2.3 反转链表的m到n个节点

    力扣92:https://leetcode-cn.com/problems/reverse-linked-list-ii/

        def reverseMtoN(self, head, m, n):
            if m == 1:
                return self.reverseN(head,n)
            head.next = self.reverseMtoN(head.next, m-1,n-1)
            return head
    
        # 方法2
        def reverseMtoN(self, head, m, n):
            if m == 1:
                return self.reverseN(head, n)
            cur = head
            pre = None
            count = 1
            while count != m:
                pre = cur
                cur = cur.next
                count += 1
            p = self.reverseN(cur, n - m + 1)
            pre.next = p
            return head  # 返回的总是头节点

    2.4 每k个一组对链表进行翻转,如果节点总数不是k的倍数,则将最后剩余的节点保持原有顺序

    力扣25:https://leetcode-cn.com/problems/reverse-nodes-in-k-group/

        def reverseK(self,head,k):
            i = 1
            temp = head
            while i < k and temp != None:
                temp = temp.next
                i += 1
            if temp == None:
                return head
    
            t2 = temp.next
            temp.next = None
            Newhead = self.reverseList(head) #要想利用反转链表这个函数,只需要将链表每k个元素用None截断
            Newtemp = self.reverseK(t2,k)
            head.next = Newtemp
            return Newhead

    2.5  每k个一组对链表进行从后往前翻转,如果节点总数不是k的倍数,则将最后剩余的节点保持原有顺序

        def RevReverK(self,head,k):
            p = self.reverseList(head)
            q = self.reverseK(p,k)
            return self.reverseList(q)

    3. 快慢指针在链表中的应用

    3.1 删除链表中的倒数第n个节点

    力扣19:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

    快慢指针的前进方向是一致的,但前进的步伐不同,快指针较快,具体快指针比慢指针快多少,要根据实际问题进行分析。

        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            #快指针先走几步,可以从结束条件开始考虑,快指针先走k-1步,这样当快指针走到最后时,慢指针指向k
            slow = head
            fast = head 
            count = 0
            while count < n-1:
                fast = fast.next
                count += 1
            if fast.next == None:
                return head.next 
            while fast.next:
                temp = slow 
                slow = slow.next
                fast = fast.next
            temp.next = slow.next 
            return head

    3.2 环形链表

    力扣:https://leetcode-cn.com/problems/linked-list-cycle/

        def hasCycle(self, head: ListNode) -> bool:
            if head == None or head.next == None:
                return False 
            slow = head 
            fast = head 
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
                if slow == fast:
                    return True
            return False

    快指针比慢指针多走一步,若链表中存在环,当快指针比慢指针多走一个环时,二者就会相遇。

    3.3 相交链表

    力扣160:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

        def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
            if headA == None or headB == None:
                return None
            pA = headA
            pB = headB
            while pA != pB:
                pA = pA.next if pA else headB
                pB = pB.next if pB else headA
            return pA

    4.用环形链表解决约瑟夫环问题

    问题描述:编号为1-N的N个士兵围坐在一起形成一个圆圈,从编号为1的士兵开始依次报数,数到m的士兵会被杀死出列,之后的士兵再从1开始报数。直到剩下最后一个士兵,求这个士兵的编号。

    #约瑟夫环问题
    class ListNode:
        def __init__(self, x):
            self.val = x
            self.next = None
    
    class LinkList:
        def __init__(self):
            self.head = None
    
        #构建环形链表
        def circleList(self,N):
            self.head = ListNode(1)
            r = self.head
            cur = self.head
            for i in range(2,N+1):
                node = ListNode(i)
                cur.next = node
                cur = cur.next
            cur.next = r
            return r
    
        def Josephus(self,N,m):
            if N < 2 or m == 1:
                return N
            head = self.circleList(N)
            p = head
            while p.next != p:
                for i in range(m-1):
                    pre = p
                    p = p.next
                pre.next = p.next
                p = pre.next
            return p.val

    这种方法的时间复杂度为O(N*m),空间复杂度为O(N),还可利用递归来解决,感兴趣的可以自行百度。

  • 相关阅读:
    鼠标放大镜案例代码
    鼠标点击跟随,鼠标点击哪里,图片跟随到哪里;
    筋斗云效果(云朵在导航栏内随着鼠标移动)
    HDU5003:Osu!(签到题)HDU5038:(签到题,题意很坑)
    SDUT3146:Integer division 2(整数划分区间dp)
    SDUT3145:Integer division 1(换零钱背包)
    SDUT3143:Combinatorial mathematics(组合数学)
    SDUT3141:Count(哈希)好题
    SDUT1574:组合数的计算
    SDUT1607:Number Sequence(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/qingming302/p/13132127.html
Copyright © 2011-2022 走看看