算法竞赛(Python)-链表

news2024/11/30 0:27:29

文章目录

  • 一 链表简介
    • 1.1链表定义
    • 1.2 双向链表
    • 1.3 循环链表
  • 二、链表的基本操作
    • 2.1 链表的结构定义
    • 2.2 建立一个线性链表
    • 2.3 求线性链表的长度
    • 2.4 查找元素
    • 2.5 插入元素
      • 2.5.1 链表头部插入元素
      • 2.5.2 链表尾部插入元素
      • 2.5.3 链表中间插入元素
    • 2.6 改变元素
    • 2.7 删除元素
      • 2.7.1 链表头部删除元素
      • 2.7.2 链表尾部删除元素
      • 2.7.3 链表中间删除元素
    • 2.8 链表题目
      • 删除排序链表中的重复元素
  • 三、链表排序
    • 3.1 链表冒泡排序
    • 3.2 链表选择排序
  • 四、链表双指针
    • 4.1 起点不一致的快慢指针
    • 4.2 步长不一致的快慢指针
    • 4.3 分离双指针


一 链表简介

1.1链表定义

  链表(Linked List):一种线性表数据结构。它使用一组任意的存储单元(可以是连续的,也可以是不连续的),来存储一组具有相同类型的数据。
  简单来说,「链表」 是实现线性表链式存储结构的基础。
  以单链表为例,链表的存储方式如下图所示。

  如上图所示,链表通过将一组任意的存储单元串联在一起。其中,每个数据元素占用若干存储单元的组合称为一个「链节点」。为了将所有的节点串起来,每个链节点不仅要存放一个数据元素的值,还要存放一个指出这个数据元素在逻辑关系上的直接后继元素所在链节点的地址,该地址被称为「后继指针 next
  在链表中,数据元素之间的逻辑关系是通过指针来间接反映的。逻辑上相邻的数据元素在物理地址上可能相邻,可也能不相邻。其在物理地址上的表现是随机的。
  我们先来简单介绍一下链表结构的优缺点:

  • 优点:存储空间不必事先分配,在需要存储空间的时候可以临时申请,不会造成空间的浪费;一些操作的时间效率远比数组高(插入、移动、删除元素等)。
  • 缺点:不仅数据元素本身的数据信息要占用存储空间,指针也需要占用存储空间,链表结构比数组结构的空间开销大。

1.2 双向链表

  双向链表(Doubly Linked List):链表的一种,也叫做双链表。它的每个链节点中有两个指针,分别指向直接后继和直接前驱。
  双向链表特点:从双链表的任意一个节点开始,都可以很方便的访问它的前驱节点和后继节点。

1.3 循环链表

  循环链表(Circular linked list):链表的一种。它的最后一个链节点指向头节点,形成一个环。
  循环链表特点:从循环链表的任何一个节点出发都能找到任何其他节点。

二、链表的基本操作

  数据结构的操作一般涉及到增、删、改、查 4 种情况,链表的操作也基本上是这 4 种情况。我们一起来看一下链表的基本操作。

2.1 链表的结构定义

  链表是由链节点通过 next 链接而构成的,我们可以先定义一个简单的「链节点类」,再来定义完整的「链表类」。

  • 链节点类(即 ListNode 类):使用成员变量 val 表示数据元素的值,使用指针变量 next 表示后继指针。
  • 链表类(即 LinkedList 类):使用一个链节点变量 head 来表示链表的头节点。

   我们在创建空链表时,只需要把相应的链表头节点变量设置为空链接即可。在 Python 里可以将其设置为 None,其他语言也有类似的惯用值,比如 NULL、0 等。

# 链节点类
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

# 链表类
class LinkedList:
    def __init__(self):
        self.head = None

2.2 建立一个线性链表

   建立一个线性链表:根据线性表的数据元素动态生成链节点,并依次将其连接到链表中。
   1、从所给线性表中取出第 1个数据元素,建立链表头节点。然后依次获取表中的数据元素。
   2、每获取一个数据元素,就为该数据元素生成一个新节点,将新节点插入到链表的尾部。
   3、插入完毕之后返回第 1 个链节点(即头节点)的地址。

# 根据 data 初始化一个新链表
def create(self, data):
    if not data:
        return
    self.head = ListNode(data[0])
    cur = self.head
    for i in range(1, len(data)):
        node = ListNode(data[i])
        cur.next = node
        cur = cur.next

   建立一个线性链表」的操作依赖于线性表的数据元素个数,因此,「建立一个线性链表」的时间复杂度为 O(n),n 为线性表长度。

2.3 求线性链表的长度

   求线性链表长度:使用指针变量 cur 顺着链表 next 指针进行移动,并使用计数器 count 记录元素个数。
   1、让指针变量 cur 指向链表的第 1 个链节点。
   2、顺着链节点的 next 指针遍历链表,指针变量 cur 每指向一个链节点,计数器就做一次计数。
   3、等 cur 指向为空时结束遍历,此时计数器的数值就是链表的长度,将其返回即可。

# 获取线性链表长度
def length(self):
    count = 0
    cur = self.head
    while cur:
        count += 1
        cur = cur.next 
    return count

2.4 查找元素

   在链表中查找值为 val 的元素:从头节点 head 开始,沿着链表节点逐一进行查找。如果查找成功,返回被查找节点的地址;否则返回 None。
   1、让指针变量 cur 指向链表的第 1 个链节点。
   2、顺着链节点的 next 指针遍历链表,如果遇到 cur.val==val,则返回当前指针变量 cur。
   3、如果 cur 指向为空时也未找到,则该链表中没有值为 val 的元素,则返回 None。

# 查找元素:在链表中查找值为 val 的元素
def find(self, val):
    cur = self.head
    while cur:
        if val == cur.val:
            return cur
        cur = cur.next

    return None

2.5 插入元素

2.5.1 链表头部插入元素

# 链表头部插入元素
def insertFront(self, val):
    node = ListNode(val)
    node.next = self.head
    self.head = node

2.5.2 链表尾部插入元素

# 链表尾部插入元素
def insertRear(self, val):
    node = ListNode(val)
    cur = self.head
    while cur.next:
        cur = cur.next
    cur.next = node

2.5.3 链表中间插入元素

# 链表中间插入元素
def insertInside(self, index, val):
    count = 0
    cur = self.head
    while cur and count < index - 1:
        count += 1
        cur = cur.next
        
    if not cur:
        return 'Error'
    
    node = ListNode(val)
    node.next = cur.next
    cur.next = node

2.6 改变元素

「将链表中第 i 个元素值改为 val」 的代码如下:

# 改变元素:将链表中第 i 个元素值改为 val
def change(self, index, val):
    count = 0
    cur = self.head
    while cur and count < index:
        count += 1
        cur = cur.next
        
    if not cur:
        return 'Error'
    
    cur.val = val

2.7 删除元素

2.7.1 链表头部删除元素

# 链表头部删除元素
def removeFront(self):
    if self.head:
        self.head = self.head.next

2.7.2 链表尾部删除元素

# 链表尾部删除元素
def removeRear(self):
    if not self.head or not self.head.next:
        return 'Error'

    cur = self.head
    while cur.next.next:
        cur = cur.next
    cur.next = None

2.7.3 链表中间删除元素

   链表中间删除元素:删除链表第 i 个链节点。
   1、先使用指针变量 cur 移动到第 i−1 个位置的链节点。
   2、然后将 cur 的 next 指针,指向要第 i 个元素的下一个节点即可。

# 链表中间删除元素
def removeInside(self, index):
    count = 0
    cur = self.head
    
    while cur.next and count < index - 1:
        count += 1
        cur = cur.next
        
    if not cur:
        return 'Error'
        
    del_node = cur.next
    cur.next = del_node.next

2.8 链表题目

删除排序链表中的重复元素

描述:给定一个已排序的链表的头 head。
要求:删除所有重复的元素,使每个元素只出现一次。返回已排序的链表。

示例输入:head = [1,1,2,3,3]
输出:[1,2,3]

思路 1:遍历
1、使用指针 curr 遍历链表,先将 head 保存到 curr 指针。
2、判断当前元素的值和当前元素下一个节点元素值是否相等。
3、如果相等,则让当前指针指向当前指针下两个节点。
4、否则,让 curr 继续向后遍历。
5、遍历完之后返回头节点 head

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if head == None:
            return head

        curr = head
        while curr.next:
            if curr.val == curr.next.val:
                curr.next = curr.next.next
            else:
                curr = curr.next
        return head

三、链表排序

   适合链表的排序算法:冒泡排序、选择排序、插入排序、归并排序、快速排序、计数排序、桶排序、基数排序。
   不适合链表的排序算法:希尔排序。
   可以用于链表排序但不建议使用的排序算法:堆排序。

3.1 链表冒泡排序

  1、使用三个指针 node_i、node_j 和 tail。其中 node_i 用于控制外循环次数,循环次数为链节点个数(链表长度)。node_j 和 tail 用于控制内循环次数和循环结束位置。
  2、排序开始前,将 node_i 、node_j 置于头节点位置。tail 指向链表末尾,即 None。
  3、比较链表中相邻两个元素 node_j.val 与 node_j.next.val 的值大小,如果 node_j.val > node_j.next.val,则值相互交换。否则不发生交换。然后向右移动 node_j 指针,直到 node_j.next == tail 时停止。
  4、一次循环之后,将 tail 移动到 node_j 所在位置。相当于 tail 向左移动了一位。此时 tail 节点右侧为链表中最大的链节点。
  5、然后移动 node_i 节点,并将 node_j 置于头节点位置。然后重复第 3、4 步操作。
  6、直到 node_i 节点移动到链表末尾停止,排序结束。
  7、返回链表的头节点 head。

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

# 链表类
class LinkedList:
    def __init__(self):
        self.head = None

    # 根据 data 初始化一个新链表
    def create(self, data):
        if not data:
            return
        self.head = ListNode(data[0])
        cur = self.head
        for i in range(1, len(data)):
            node = ListNode(data[i])
            cur.next = node
            cur = cur.next

#冒泡排序
class Solution:
    def sectionSort(self, head: ListNode):
        node_i = head
        # node_i 为当前未排序链表的第一个链节点
        while node_i and node_i.next:
            # min_node 为未排序链表中的值最小节点
            min_node = node_i
            node_j = node_i.next
            while node_j:
                if node_j.val < min_node.val:
                    min_node = node_j
                node_j = node_j.next
            # 交换值最小节点与未排序链表中第一个节点的值
            if node_i != min_node:
                node_i.val, min_node.val = min_node.val, node_i.val
            node_i = node_i.next

        return head

    def sortList(self, head):
        """
        :param head:[ListNode]的head
        :return:
        """
        return self.sectionSort(head)


if __name__ =="__main__":
    data=[3,1,5,7,2]
    C=LinkedList()
    C.create(data) #创建链表
    D=Solution()
    D.sortList(C.head)#排序
    #打印
    result=[]
    node_i = C.head
    while node_i:
        result.append(node_i.val)
        node_i = node_i.next
    print("结果:",result)

3.2 链表选择排序

1、使用两个指针 node_i、node_j。node_i 既可以用于控制外循环次数,又可以作为当前未排序链表的第一个链节点位置。
2、使用 min_node 记录当前未排序链表中值最小的链节点。
3、每一趟排序开始时,先令 min_node = node_i(即暂时假设链表中 node_i 节点为值最小的节点,经过比较后再确定最小值节点位置)。
4、然后依次比较未排序链表中 node_j.val 与 min_node.val 的值大小。如果 node_j.val < min_node.val,则更新 min_node 为 node_j。
5、这一趟排序结束时,未排序链表中最小值节点为 min_node,如果 node_i != min_node,则将 node_i 与 min_node 值进行交换。如果 node_i == min_node,则不用交换。
6、排序结束后,继续向右移动 node_i,重复上述步骤,在剩余未排序链表中寻找最小的链节点,并与 node_i 进行比较和交换,直到 node_i == None 或者 node_i.next == None 时,停止排序。
7、返回链表的头节点 head。


class Solution:
    def sectionSort(self, head: ListNode):
        node_i = head
        # node_i 为当前未排序链表的第一个链节点
        while node_i and node_i.next:
            # min_node 为未排序链表中的值最小节点
            min_node = node_i
            node_j = node_i.next
            while node_j:
                if node_j.val < min_node.val:
                    min_node = node_j
                node_j = node_j.next
            # 交换值最小节点与未排序链表中第一个节点的值
            if node_i != min_node:
                node_i.val, min_node.val = min_node.val, node_i.val
            node_i = node_i.next

        return head

    def sortList(self, head):
        """
        :param head:[ListNode]的head
        :return:
        """
        return self.sectionSort(head)

四、链表双指针

  双指针(Two Pointers):指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。如果两个指针方向相反,则称为「对撞时针」。如果两个指针方向相同,则称为「快慢指针」。如果两个指针分别属于不同的数组 / 链表,则称为「分离双指针」。
  而在单链表中,因为遍历节点只能顺着 next 指针方向进行,所以对于链表而言,一般只会用到「快慢指针」和「分离双指针」。其中链表的「快慢指针」又分为「起点不一致的快慢指针」和「步长不一致的快慢指针」。

4.1 起点不一致的快慢指针

  起点不一致的快慢指针:指的是两个指针从同一侧开始遍历链表,但是两个指针的起点不一样。 快指针 fast 比慢指针 slow 先走 n 步,直到快指针移动到链表尾端时为止。
  1、使用两个指针 slow、fast。slow、fast 都指向链表的头节点,即:slow = head,fast = head。
  2、先将快指针向右移动 n 步。然后再同时向右移动快、慢指针。
  3、等到快指针移动到链表尾部(即 fast == None)时跳出循环体。
伪代码模板

slow = head
fast = head

while n:
    fast = fast.next
    n -= 1
while fast:
    fast = fast.next
    slow = slow.next

适用范围
  起点不一致的快慢指针主要用于找到链表中倒数第 k 个节点、删除链表倒数第 N 个节点等。

删除链表的倒数第 N 个结点
描述:给定一个链表的头节点 head。
要求:删除链表的倒数第 n 个节点,并且返回链表的头节点。

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
输入:head = [1], n = 1
输出:[]

如果用一次遍历实现的话,可以使用快慢指针。让快指针先走 n 步,然后快慢指针、慢指针再同时走,每次一步,这样等快指针遍历到链表尾部的时候,慢指针就刚好遍历到了倒数第 n 个节点位置。将该位置上的节点删除即可。

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

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        newHead = ListNode(0, head) #插入一个0
        fast = head
        slow = newHead
        while n:
            fast = fast.next
            n -= 1
        while fast:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return newHead.next

4.2 步长不一致的快慢指针

  步长不一致的快慢指针:指的是两个指针从同一侧开始遍历链表,两个指针的起点一样,但是步长不一致。例如,慢指针 slow 每次走 1 步,快指针 fast 每次走两步。直到快指针移动到链表尾端时为止。
  1、使用两个指针 slow、fast。slow、fast 都指向链表的头节点。
  2、在循环体中将快、慢指针同时向右移动,但是快、慢指针的移动步长不一致。比如将慢指针每次移动 1 步,即 slow = slow.next。快指针每次移动 2 步,即 fast = fast.next.next。
  3、等到快指针移动到链表尾部(即 fast == None)时跳出循环体。

伪代码

fast = head
slow = head

while fast and fast.next:
    slow = slow.next
    fast = fast.next.next

适用范围
步长不一致的快慢指针适合寻找链表的中点、判断和检测链表是否有环、找到两个链表的交点等问题。

链表的中间结点
描述:给定一个单链表的头节点 head。
要求:返回链表的中间节点。如果有两个中间节点,则返回第二个中间节点。

class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        fast = head
        slow = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        return slow

4.3 分离双指针

分离双指针:两个指针分别属于不同的链表,两个指针分别在两个链表中移动。
1、使用两个指针 left_1、left_2。left_1 指向第一个链表头节点,即:left_1 = list1,left_2 指向第二个链表头节点,即:left_2 = list2。
2、当满足一定条件时,两个指针同时右移,即 left_1 = left_1.next、left_2 = left_2.next。
3、当满足另外一定条件时,将 left_1 指针右移,即 left_1 = left_1.next。
4、当满足其他一定条件时,将 left_2 指针右移,即 left_2 = left_2.next。
5、当其中一个链表遍历完时或者满足其他特殊条件时跳出循环体。

伪代码

left_1 = list1
left_2 = list2

while left_1 and left_2:
    if 一定条件 1:
        left_1 = left_1.next
        left_2 = left_2.next
    elif 一定条件 2:
        left_1 = left_1.next
    elif 一定条件 3:
        left_2 = left_2.next

适用范围
分离双指针一般用于有序链表合并等问题。

合并两个有序链表
描述:给定两个升序链表的头节点 list1 和 list2。
要求:将其合并为一个升序链表。

输入:list1 = [1,2,4], list2 = [1,3,4]
输出:[1,1,2,3,4,4]
输入:list1 = [], list2 = []
输出:[]

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        dummy_head = ListNode(-1)

        curr = dummy_head
        while list1 and list2:
            if list1.val <= list2.val:
                curr.next = list1
                list1 = list1.next
            else:
                curr.next = list2
                list2 = list2.next
            curr = curr.next

        curr.next = list1 if list1 is not None else list2

        return dummy_head.next

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity ShaderLab 实现网格爆炸

实现思路&#xff1a; 沿着3D物体每个面的法线&#xff0c;将面偏移一定的位置。 Shader Graph实现如下&#xff1a; Shader Lab 实现如下&#xff1a; Shader "Unlit/MeshExplode" {Properties{_MainTex ("Texture", 2D) "white" {}_Distan…

快速上手:如何开发一个实用的 Edge 插件

在日常浏览网页时&#xff0c;背景图片能够显著提升网页的视觉体验。如果你也想为自己的浏览器页面添加个性化背景图片&#xff0c;并希望背景图片设置能够持久保存&#xff0c;本文将介绍如何通过开发一个自定义Edge插件来实现这一功能。我们将涵盖保存背景设置到插件选项页&a…

【Maven】功能和核心概念

1. 什么是Maven 1.1 Maven的概念 Maven 是 Apache 软件基金会组织维护的一款自动化构建工具&#xff0c;专注服务于 Java 平台的项目构建和依赖管理。 1.2 为什么要使用Maven&#xff1f; 在项目开发中&#xff0c;我们需要引用各种 jar 包&#xff0c;引用的 jar 包可能有…

神经网络归一化方法总结

在深度学习中&#xff0c;归一化 是提高训练效率和稳定性的关键技术。以下是几种常见的神经网络归一化方法的总结&#xff0c;包括其核心思想、适用场景及优缺点。 四种归一化 特性Batch NormalizationGroup NormalizationLayer NormalizationInstance Normalization计算维度…

视频汇聚平台Liveweb国标GB28181视频平台监控中心设计

在现代安防视频监控领域&#xff0c;Liveweb视频汇聚平台以其卓越的兼容性和灵活的拓展能力&#xff0c;为用户提供了一套全面的解决方案。该平台不仅能够实现视频的远程监控、录像、存储与回放等基础功能&#xff0c;还涵盖了视频转码、视频快照、告警、云台控制、语音对讲以及…

hubu新星杯实践能力赛模拟赛web/Misc-wp

ez_eval <?php highlight_file(__FILE__); error_reporting(0);$hubu $_GET[hubu];eval($hubu);?> 先进行代码审计&#xff0c;GET传参hubu&#xff0c;并执行命令&#xff0c;没有任何绕过&#xff0c;放开手脚去做 payload: ?hubusystem(cat /f*); #直接rcerc…

【前端】跨域问题与缓存

报错如下&#xff1a; 原因&#xff1a; 浏览器 缓存跨域&#xff0c;顾名思义是由于浏览器的缓存机制导致的一种跨域情况。这种跨域一般会出现在浏览器通过一些无视跨域的标签和css(如img、background-image)缓存了一些图片资源之后&#xff0c;当再次发起图片请求时&#xff…

抓包之OSI七层模型以及TCPIP四层模型

写在前面 本文看下OSI七层模型以及TCP/IP四层网络模型&#xff0c;并尝试使用wireshark进行验证。 1&#xff1a;OSI七层网络模型和TCP/IP四层模型 全称&#xff1a;open system interconnection。 需要注意OSI七层模型最终是没有落地的&#xff0c;最终落地的是与之类似的…

#渗透测试#红蓝攻防#HW#漏洞挖掘#漏洞复现02-永恒之蓝漏洞

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

MTK 展锐 高通 sensorhub架构

一、MTK平台 MTK框架可以分为两部分&#xff0c;AP和SCP。 AP是主芯片&#xff0c;SCP是协处理器&#xff0c;他们一起工作来处理sensor数据。 SCP 是用来处理sensor和audio相关功能和其他客制化需求的一个协处理理器&#xff0c;MTK SCP选择freeRTOS作为操作系统&#xff0c…

视觉语言模型(VLM)学习笔记

目录 应用场景举例 VLM 的总体架构包括&#xff1a; 深度解析&#xff1a;图像编码器的实现 图像编码器&#xff1a;视觉 Transformer 注意力机制 视觉-语言投影器 综合实现 训练及注意事项 总结 应用场景举例 基于文本的图像生成或编辑&#xff1a;你输入 “生成一张…

[AutoSar]BSW_Diagnostic_007 BootLoader 跳转及APP OR boot response 实现

目录 关键词平台说明背景一、Process Jump to Bootloader二、相关函数和配置2.1 Dcm_GetProgConditions()2.2 Dcm_SetProgConditions() 三、如何实现在APP 还是BOOT 中对10 02服务响应3.1 配置3.2 code 四、报文五、小结 关键词 嵌入式、C语言、autosar、OS、BSW、UDS、diagno…

如何启用本机GPU硬件加速猿大师播放器网页同时播放多路RTSP H.265 1080P高清摄像头RTSP视频流?

目前市面上主流播放RTSP视频流的方式是用服务器转码方案&#xff0c;这种方案的好处是兼容性更强&#xff0c;可以用于不同的平台&#xff0c;比如&#xff1a;Windows、Linux或者手机端&#xff0c;但是缺点也很明显&#xff1a;延迟高、播放高清或者同时播放多路视频视频容易…

设置ip和代理DNS的WindowsBat脚本怎么写?

今天分享一个我们在工作时&#xff0c;常见的在Windows中通过批处理脚本&#xff08;.bat 文件&#xff09;来设置IP地址、代理以及DNS 相关配置的示例&#xff0c;大家可以根据实际需求进行修改调整。 一、设置静态IP地址脚本示例 以下脚本用于设置本地连接&#xff08;你可…

深度学习-49-AI应用实战之基于HyperLPR的车牌识别

文章目录 1 车牌识别系统1.1 识别原理1.1.1 车牌定位1.1.2 字符识别2 实例应用2.1 安装hyperlpr32.2 识别结果2.3 可视化显示2.4 结合streamlit3 附录3.1 PIL.Image转换成OpenCV格式3.2 OpenCV转换成PIL.Image格式3.3 st.image嵌入图像内容3.4 参考附录1 车牌识别系统 车牌识别…

基于深度学习的手势识别算法

基于深度学习的手势识别算法 概述算法原理核心逻辑效果演示使用方式参考文献 概述 本文基于论文 [Simple Baselines for Human Pose Estimation and Tracking[1]](ECCV 2018 Open Access Repository (thecvf.com)) 实现手部姿态估计。 手部姿态估计是从图像或视频帧集中找到手…

【Linux】-操作系统

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;深入代码世界&#xff0c;了解掌握 Linux 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ​​ 一、冯•诺依曼架构&#xff…

2024最新python使用yt-dlp

2024最新python使用yt-dlp下载YT视频 1.获取yt的cookie1&#xff09;google浏览器下载Get cookies.txt LOCALLY插件2&#xff09;导出cookie 2.yt-dlp下载[yt-dlp的GitHub地址](https://github.com/yt-dlp/yt-dlp?tabreadme-ov-file)1&#xff09;使用Pycharm(2024.3)进行代码…

Mybatis集成篇(一)

Spring 框架集成Mybatis 目前主流Spring框架体系中&#xff0c;可以集成很多第三方框架&#xff0c;方便开发者利用Spring框架机制使用第三方框架的功能。就例如本篇Spring集成Mybatis 简单集成案例&#xff1a; Config配置&#xff1a; Configuration MapperScan(basePack…

C51相关实验

C51相关实验 LED (P2 / 0~7)蜂鸣器 (P2^5)数码管 (P0 0~7 段 &#xff0c;P2 2~4 位)独立按键 &#xff08;P3^1 P3^0 P3^2 P3^3&#xff09;直流电机 (J47 5v 01~04)综合实验矩阵按键 (P1组 0~7)LED点阵 LED (P2 / 0~7) //功能&#xff1a;1.让开发板的LED全亮&#xff0c;2,…