链表章节 leetcode 思路&实现

203. 移除链表元素

思路,设定一个虚拟头节点防止原始的头节点被删了需要讨论,其他很简单

简单复习一下节点的定义

python 复制代码
class ListNode:
    def __init__(self, val, next):
        self.next = next
        self.val = val
python 复制代码
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy = ListNode()
        dummy.next = head
        node = dummy

        while node.next is not None:
            if node.next.val == val:
                node.next = node.next.next
            else:
                node = node.next
        return dummy.next

707. 设计链表

思路:怎么搞了个链表长度来orz

思路也比较清晰,难度不是很大,基本功的题目

python 复制代码
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
        
class MyLinkedList:
    def __init__(self):
        self.dummy = ListNode()
        self.size = 0

    def get(self, index: int) -> int:
        if index < 0 or index >= self.size:
            return -1
        
        node = self.dummy.next
        for i in range(index):
            node = node.next
            
        return node.val

    def addAtHead(self, val: int) -> None:
        self.dummy.next = ListNode(val, self.dummy.next)
        self.size += 1

    def addAtTail(self, val: int) -> None:
        node = self.dummy
        while node.next:
            node = node.next
        node.next = ListNode(val)
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0 or index > self.size:
            return
        
        node = self.dummy
        for i in range(index):
            node = node.next
        node.next = ListNode(val, node.next)
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:
            return
        
        node = self.dummy
        for i in range(index):
            node = node.next
        node.next = node.next.next
        self.size -= 1


# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

206. 反转链表

思路,考虑当前节点和上一个节点cur 和 pre:初始指向头节点和空节点,向后顺延,在cur不为空时,用temp标注cur的下一个节点,先让cur指向pre,再让pre换到cur的位置,cur换到temp的位置即可

python 复制代码
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        cur, pre = head, None
        while cur:
            temp = cur.next
            cur.next = pre 
            pre = cur
            cur = temp
        return pre

24. 两两交换链表中的节点

思路:设定一个虚拟节点指向head.next,便于后面返回,针对每一次情况,设定pre为当前节点的上一个,cur为当前节点

采用思路:想用递归的方法试一试,当交换完前两个节点之后,即再次对后面两个节点进行处理,也可以理解为对一个失去了前两个节点的新链表进行处理,合理引入递归。

考虑递归的操作,pre节点指向第一个,cur节点指向第二个:全部交换之后期待1节点指向4节点,也即指向交换后的第二组cur,2节点期待指向1节点,也即再递归新的链表。头节点为cur.next:

python 复制代码
pre.next = self.swapPairs(cur.next)
cur.next - pre

整体代码如下:

python 复制代码
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head is None or head.next is None:
            return head
        pre = head
        cur = head.next

        pre.next = self.swapPairs(cur.next)
        cur.next = pre
        return cur

19. 删除链表的倒数第 N 个结点

思路:设定一个虚拟节点指向头节点,node放在虚拟节点上,node取到下一个时,n-=1,如果node为空则直接返回虚拟节点的next,当n=1则执行删除,让该节点直接指向next的next即可

上面的思路不对,是倒数第n个节点

正确思路:让一个节点先走n步,然后再让两个节点从不同起始点出发,到达终点时,慢节点也到达了要删的节点前面,就很显然了。

python 复制代码
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummy = ListNode(val = 1)
        dummy.next = head
        node1 = dummy
        while n != 0:
            node1 = node1.next
            n -= 1
        node2 = dummy
        while node1.next is not None:
            node1 = node1.next
            node2 = node2.next
        node2.next = node2.next.next
        return dummy.next

再考虑一下递归:也即不断地获取节点的相对位置。给定一个虚拟节点指向头节点,从虚拟节点向后一直遍历到最后一个节点后面。也即第0个节点,此时递归函数返回0,让count = DFS(node.next)+ 1,需要获取dfs函数的值时就继续带入,直到获得0,依次返回,直到找到count等于n+1时,此时让该节点指向下下个即可

python 复制代码
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummy = ListNode(0,head)

        def DFS(node):
            if node is None:
                return 0
            count = DFS(node.next)+1
            if count == n+1:
                node.next = node.next.next
            return count

        DFS(dummy)
        return dummy.next

面试题 02.07. 链表相交

思路:考虑到将两个链表和并,如果二者有交点,一定会交会。停止条件是二者相等,此时遇见了或者都到达空节点。返回任意一节点即可。数学思想

python 复制代码
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        nodea,nodeb = headA,headB
        while nodea != nodeb:
            nodea = nodea.next if nodea is not None else headB
            nodeb = nodeb.next if nodeb is not None else headA

        return nodea

142. 环形链表 II

思路:数学问题:快慢指针,慢指针走一个快指针走两个,如有环一定相遇,如无环快指针会滞空,所以让判定条件是快指针以及快指针的下一个节点不空。获得交点后,考虑从交点出发比从起点出发都走了k步,于是再走一次,会在入口点相遇

python 复制代码
class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow,fast = head,head
        while fast is not None and fast.next is not None:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                flag = slow
                slow = head
                while slow != flag:
                    slow = slow.next
                    flag = flag.next
                return flag
        return None
相关推荐
Dr.F.Arthur2 小时前
我的算法学习笔记——链表篇
数据结构·笔记·学习·链表
DowneyJoy2 小时前
【Unity3D补充知识点】常用数据结构分析-数组(Array)
数据结构·unity·c#
程序员zgh3 小时前
C++ 环形队列 从原理到实例演示
c语言·开发语言·数据结构·c++·学习
Trouvaille ~3 小时前
【优选算法篇】拓扑排序——逻辑先后与任务依赖的终极拆解
数据结构·c++·算法·leetcode·青少年编程·蓝桥杯·拓扑学
XiYang-DING3 小时前
【LeetCode】118.杨辉三角
算法·leetcode·职场和发展
CylMK3 小时前
题解:UVA1218 完美的服务 Perfect Service
数据结构·c++·算法·深度优先·图论
重生之我是Java开发战士3 小时前
【广度优先搜索】BFS解决拓扑排序:课程表I,课程表II,火星词典
算法·leetcode·广度优先
丶小鱼丶3 小时前
数据结构和算法之【阻塞队列】上篇
java·数据结构
人道领域3 小时前
LeetCode【刷题日记】:滑动窗口算法详解:从暴力法到最优解
java·算法·leetcode