四、链表————相关算法探讨(持续更新中)

news2024/11/25 23:48:45

链表中相关算法探讨

  • 前言
  • 一、移除链表元素
    • 1.1 思路分析
    • 1.2 解法探讨
      • 1.2.1 直接删除
      • 1.2.2 创建虚拟头节点来删除
      • 1.2.3 递归版删除
  • 二、反转列表
    • 2.1 思路分析
    • 2.2 做法
      • 2.2.1 创建新链表方式
      • 2.2.2 双指针法
      • 2.2.3 递归法
  • 三、两两交换链表中的节点
    • 3.1 思路分析
    • 3.2 解法探讨
      • 3.2.1 不使用虚拟头节点(递归法)
      • 3.2.2 使用虚拟头节点
  • 四、删除链表的倒数第N个节点
    • 4.1 思路分析
    • 4.2 解法探讨
      • 4.2.1 两次遍历
      • 4.2.2 双指针法
        • 4.2.2.1 一次遍历(不使用虚拟头节点)
        • 4.2.2.2 一次遍历(使用虚拟头节点)
      • 4.2.3 递归法
  • 五、链表相交
    • 5.1 思路分析
    • 5.2 解法探讨
      • 5.2.1
  • 六、环形链表II
    • 6.1 思路分析
    • 6.2 解法探讨
      • 6.2.1
  • 总结


前言

  • 接下来,我们一起学习力扣中跟链表有关的算法题。

一、移除链表元素

  • 力扣算法题目第 203 题:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
  • 示例 1:
    在这里插入图片描述
    输入: head = [1,2,6,3,4,5,6], val = 6
    输出: [1,2,3,4,5]
  • 示例 2:
    输入: head = [ ], val = 1
    输出: [ ]
  • 前提:
    • 列表中的节点数目在范围 [ 0, 1 0 4 10^4 104] 内
    • 1 <= Node.val <= 50
    • 0 <= val <= 50

1.1 思路分析

  • 将要删除节点的前一个节点的next指向删除节点的下一个节点的地址,就可以删除这个节点。

1.2 解法探讨

1.2.1 直接删除

  • 我们首先检查头节点head是否是要删除的节点,如果是,则不断前进直到找到不是要删除的节点或者到达链表末尾。
  • 如果整个链表都是要删除的节点,则最终head会变成None。
  • 接下来进入常规的遍历过程,从head开始遍历,对于每一个节点current,如果它的下一个节点是需要删除的节点,则跳过这个节点,否则就继续前进。

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

# 先定义节点类,定义节点的初始化方法
class ListNode:
    def __init__(self, val=0, next=None):
    	# 定义属性 val 存储节点的值  next用来 指向下一个节点的地址
        self.val = val
        self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int):

		# 如果第一个节点就是空的,说明链表为空,此时 直接返回空
        if head is None:
            return None
            
    	# 当第一个节点不是空的 并且就是我们要删除的元素
        while head is not None and head.val == val:
         	# 将头节点直接赋予 原链表的第二个元素,这样就删除了第一个节点
            head = head.next
		      
        # 除了上述特殊情况外,我们需要定义一个指针cur 指向原链表中的第一个节点
        cur = head
        # 当cur指向的节点不为空,并且他的下一个节点也不为空,我们就进行循环遍历,
        # 因为我们判断的就是cur指向的节点的下一个节点的状态 这样能保证我们将cur的next赋值的时候能有值
        while cur is not None and cur.next is not None:
        	# 如果cur指向的节点的下一个节点是我们要删除的
            if cur.next.val == val:
            	# 走到这 说明找到要删除的节点,那就将 cur的next指针 指向 下下个元素
                cur.next = cur.next.next
            # 走到这说明,cur指向的节点的下一个节点不是我们要删除的节点, 那就让cur指向原链表的下一个节点
            else:
                cur = cur.next
        # 返回 头节点 也就是 链表的头
        return head
        

1.2.2 创建虚拟头节点来删除

  • 在涉及到 对链表的增删操作的时候,通常设置虚拟头节点会非常便于理解,同时操作也变得非常方便。

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)


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_head = ListNode(0, head)
        # 使用 cur 指向虚拟头节点 
        cur = dummy_head

        # 开始遍历链表寻找要删除的节点
        # 当cur 指向的节点的下一个元素不为空。也就是不是尾节点
        while cur.next is not None:
        	# 如果 cur 指针指向的 当前节点的下一个节点就是我们要删除的节点
            if cur.next.val == val:
            	# 那么就让当前cur 指向的节点的 next 指向 cur 的下下个节点,
            	# 这样就跳过了cur的下一个节点,也就是删除了
                cur.next = cur.next.next
            else:
            # 否则,移动到下一个节点
                cur = cur.next

        # 返回新的头结点
        return dummy_head.next

1.2.3 递归版删除

  • 因为每个节点要进行的操作都一样,都是检查是否是要删除的节点,如果是,那么就删除,不是的话就判断下一个节点。

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)


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]:
        # 如果链表为空,直接返回None
        if head is None:
            return None
    
        # 处理当前节点
        if head.val == val:
        # 如果当前节点需要删除,则递归调用removeElements并跳过当前节点
            return self.removeElements(head.next, val)
        else:
        # 当前节点不需要删除,则处理下一个节点
            head.next = self.removeElements(head.next, val)
            return head

二、反转列表

  • 力扣算法题目第 203 题:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
  • 示例 1:
    在这里插入图片描述
    输入: head = [ 1, 2, 3, 4, 5 ]
    输出: [ 5, 4, 3, 2, 1 ]
  • 示例 2:
    输入: head = [ 1, 2 ]
    输出: [ 2, 1 ]
  • 示例 3:
    输入: head = [ ]
    输出: [ ]
  • 前提:
    • 链表中节点的数目范围是 [ 0, 5000 ]
    • -5000 <= Node.val <= 5000

2.1 思路分析

  • 如果再定义一个新的链表,然后遍历原来的链表,再依次将原来链表的值插进新链表,这会浪费内存空间,不过我们下边也会介绍这种做法,其实只要改变头节点跟next的指针指向即可。

2.2 做法

2.2.1 创建新链表方式

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( n ) O(n) O(n)

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
         # 初始化一个空的新链表
        reversed_head = None
        
        # 遍历原链表
        current = head
        while current:
            # 创建一个新节点,值为当前节点的值
            new_node = ListNode(current.val)
            
            # 将新节点连接到新链表的头部
            new_node.next = reversed_head
            reversed_head = new_node
            
            # 移动到原链表的下一个节点
            current = current.next
        
        return reversed_head

2.2.2 双指针法

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 设置 双指针 cur指向头节点 pre 先指向 头节点前面 也就是None
        cur = head
        pre = None
        # 从头节点开始遍历链表
        while cur:
            # 设置tmp存储 原链表的头节点的下一个节点的,因为下边改变指向方向后,会丢失原链表
            tmp = cur.next
            # 这一步就是改变链表指向方向的
            cur.next = pre

            # 改变指示方向后要更新 cur跟pre的值
            pre = cur
            cur = tmp
        # 返回的是pre 因为遍历完pre刚好指向原链表的最后一个节点, 也就是新链表的头节点
        return pre

2.2.3 递归法

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 调用翻转函数, 传入头结点跟None 
        return self.reverse(head, None)
    
    # 定义 翻转函数
    def reverse(self, cur: ListNode, pre: ListNode) ->ListNode:
        # 如果cur空的话,也就是头结点是空的,那么就返回None
        if cur == None:
        	# 递归出口
            return pre

        # 用 tmp 用来保存 cur 后边的那个节点
        tmp = cur.next
        # 翻转 链表中的指针方向
        cur.next = pre

        # 递归调用 reverse 传入改变 后的参数
        return self.reverse(tmp, cur)

三、两两交换链表中的节点

  • 力扣算法题目第 24 题:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
  • 示例 1:
    在这里插入图片描述
    输入: head = [ 1, 2, 3, 4 ]
    输出: [ 2, 1, 4, 3 ]
  • 示例 2:
    输入: head = [ 1 ]
    输出: [ 1 ]
  • 示例 3:
    输入: head = [ ]
    输出: [ ]
  • 前提:
    • 链表中节点的数目在范围 [ 0, 100 ] 内
    • 0 <= Node.val <= 100

3.1 思路分析

  • 两两交换链表中的节点,我们就需要两个指针指向要交换的两个节点,还需要保存第二个节点的next 防止丢失,循环遍历链表中的节点,依次完成这个动作。
  • 也可以使用虚拟头节点,这样更好理解一点

3.2 解法探讨

3.2.1 不使用虚拟头节点(递归法)

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( n ) O(n) O(n)

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
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
        
        # 重置头节点
        head = head.next.next
        
        # 交换两个指针的指向
        cur.next = pre

        # 因为 swapPairs 返回值就是上一次的头节点的指向
        pre.next = self.swapPairs(head)

        # 返回cur 因为cur指向的就是交换后的第一个节点
        return cur

3.2.2 使用虚拟头节点

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 创建一个哑节点并将其next指向head
        dummy = ListNode(0)
        dummy.next = head
        # 初始化一个当前节点指针
        current = dummy
    
        while current.next and current.next.next:
            # 初始化A、B两个节点
            A = current.next
            B = current.next.next
        
            # 交换A和B
            current.next = B
            A.next = B.next
            B.next = A
        
            # 移动current指针到交换后的B节点后面
            current = A
    
        # 返回哑节点之后的节点
        return dummy.next

四、删除链表的倒数第N个节点

  • 力扣算法题目第 19 题:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
  • 示例 1:
    在这里插入图片描述
    输入: head = [ 1, 2, 3, 4, 5 ] , n = 2
    输出: [ 1, 2, 3, 5 ]
  • 示例 2:
    输入: head = [ 1 ] , n = 1
    输出: [ ]
  • 示例 3:
    输入: head = [ 1, 2 ] , n = 1
    输出: [ 1 ]
  • 前提:
    • 链表中结点的数目为 sz
    • 1 <= sz <= 30
    • 0 <= Node.val <= 100
    • 1 <= n <= sz

4.1 思路分析

  • 因为我们不知道倒数的第 n 个节点是正着数的第几个节点, 所以我们需要遍历两次,第一次拿到链表长度,第二次根据长度跟倒数的 n 个节点,就能推出来要删除正数第几个节点
  • 还可以用双指针,双指针之间有n个节点, 那么当其中一个指针指到末尾的时候,另一个指针就是倒数的第 n 个节点
  • 还可以使用递归来做

4.2 解法探讨

4.2.1 两次遍历

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # 定义一个length 用来存放 链表长度
        length = 0
        # 定义指针指向头节点
        tmp = head
        # 循环链表 
        while tmp:
            # 获取链表长度
            length += 1
            tmp = tmp.next
        
        # 获取到链表长度就要处理 特殊值, 如果倒数第 n 个节点刚好是头节点    
        if length == n:
            # 那就返回头节点的 下一个节点当头节点
            return head.next
        
        # 获取到链表长度后 再次进行遍历 这次根据链表长度以及 n 
        # 我们能推断出要删除的节点是正着数的第几个节点
        i = 1
        pre = head
        # 遍历找到要删除的节点的前一个节点 
        while i < length - n:
            pre = pre.next
            i = i +1

        # 使用要删除节点的前一个节点 链接到 要删除节点的后一个节点
        pre.next = pre.next.next

        # 返回 头节点
        return head        

4.2.2 双指针法

4.2.2.1 一次遍历(不使用虚拟头节点)

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # 定义 pre 指向 头节点 定义 cur指向 头节点的后边那个节点
        pre = head
        cur = head.next

        # 先让cur走 n - 1 步 这样 当pre跟cur一起移动的时候
        # 当 cur走到最后一个节点的时候,这样 pre 刚好就是要删除的节点的前一个节点
        i = 1
        while i < n:
            cur = cur.next
            i += 1
        
        # 处理特殊值,不然cur越界 会报错
        # 如果 移动了 n 步以后 cur 刚好为None 那么说明链表长度为 n
        # 此时需要删除头节点, 头节点的下一个节点充当头节点 
        if cur is None:
            return head.next
        
        # 此时 pre 跟 cur 一起往后移动 当 cur指向最后一个节点的时候停止
        while cur.next:
            pre = pre.next

            cur = cur.next

        # 使用 要删除节点的前一个节点 指向 删除节点的后一个节点
        pre.next = pre.next.next
        
        # 返回 头结点
        return head
4.2.2.2 一次遍历(使用虚拟头节点)

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        
        # 创建虚拟头节点,用dummy 来指向 头节点 
        dummy = ListNode(0, head)
    
        # 初始化两个指针 刚开始都指向 虚拟头节点
        first = second = dummy
    
        # 拉开距离, 让 first指针移动 n 个位置 这样 first 跟 second 就会相差n个位置
        for _ in range(n + 1):
            first = first.next
    
        # 同步移动, 当first指针移动到最后的时候,此时 second指向的就是 倒数第 n 个节点
        while first:
            first = first.next
            second = second.next
    
        # 删除节点
        second.next = second.next.next
    
        # 返回头节点
        return dummy.next

4.2.3 递归法

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        
        def helper(node):
            if not node:
            # 如果到达链表末尾,则返回当前节点的位置(距离末尾的距离)
                return 0
        
            # 递归调用,返回下一个节点的位置
            pos = helper(node.next)
        
            # 如果当前位置正好是要删除的节点的前一个位置
            if pos == n :
                node.next = node.next.next
        
            return pos  + 1 
    
        # 创建虚拟头节点
        dummy = ListNode(0, head)
    
         # 调用递归函数
        helper(dummy)
    
        # 返回新的头节点
        return dummy.next
    



五、链表相交

5.1 思路分析

5.2 解法探讨

5.2.1

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)




六、环形链表II

6.1 思路分析

6.2 解法探讨

6.2.1

时间复杂度 O ( n ) O(n) O(n)

空间复杂度 O ( 1 ) O(1) O(1)





总结

  • 以上就是力扣中有关链表的题目的解题思路跟代码,我只是列举出来 我能想到的几种办法,如有其他解法,可以后台私信我。

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

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

相关文章

重磅 | 清华大学刘知远老师领衔的大模型公开课2024年第二季来了!助教阵容强大,零基础大模型从入门到精通,看这个就够了!

本文由readlecture.cn转录总结。ReadLecture专注于音、视频转录与总结&#xff0c;2小时视频&#xff0c;5分钟阅读&#xff0c;加速内容学习与传播。 更多讲座、采访干货内容&#xff0c;欢迎关注公众号“ReadLecture”获取&#xff01;公众号后台直接回复&#xff0c;可与公众…

RK3568笔记六十四:SG90驱动测试

若该文为原创文章,转载请注明原文出处。 前面有测试过PWM驱动,现在使用两种方式来产生PWM驱动SG90,实现舵机旋转任意角度 方法一:使用硬件PWM 方法二:使用高精度定时器,GPIO模拟PWM. 一、PWM子系统框架 二、SG90控制方法 舵机的控制需要MCU产生一个周期为20ms的脉冲信号…

python实现DES算法

DES算法 一、算法介绍1.1 背景1.2 原理1.3 基本功能函数1.3.1 初始置换函数 I P IP IP1.3.2 f f f 轮函数1.3.3 逆初始置换函数 I P − 1 IP^{-1} IP−1 1.4 子密钥的生成 二、代码实现2.1 子密钥生成实现2.2 DES加解密实现2.3 完整代码 三、演示效果 一、算法介绍 1.1 背景…

SpringBoot框架在旅游管理中的应用与实践

第三章 系统分析 3.1可行性分析 对所有的系统来说&#xff0c;都有可能会受到时间和空间上的制约。所以&#xff0c;我们在设计每一个项目的时候&#xff0c;必须对该系统实行可行性分析&#xff0c;这样不但能够降低项目的危害&#xff0c;还能改降低人力、物力和财力的损耗。…

C++(十七) 多态

一、 多态概念 多态&#xff08;polymorphism&#xff09;&#xff0c;通俗来说&#xff0c;就是多种形态。多态分为编译时多态&#xff08;静态多态&#xff09;和运行时多态&#xff08;动态多态&#xff09;。这里我们重点讲运行时多态&#xff0c;同时简单介绍编译时多态。…

swagger2.9.2 和 springboot3.3.4版本冲突问腿

swagger2.9.2 和 springboot3.3.4版本冲突问腿 问题描述&#xff1a;当我们使用 swagger 2.9.2版本的时候&#xff0c;如果恰好我们使用的 springboot 版本是3.x版本&#xff0c;会出现启动报错的问题 解决办法&#xff1a;直接使用swagger 3.x 版本和 springboot 3.x 版本 …

window 安装永洪BI Desktop版本教程

本教程基于永洪BI Desktop 10.2 一、下载软件包 &#xff08;下载需要注册&#xff0c;以便接收License邮件激活码&#xff09;&#xff0c;地址如下&#xff1a;桌面智能数据分析工具_vividime Desktop数据分析软件-永洪科技vividime Desktop是一款轻量级桌面智能数据分析工具…

【探测器】线阵相机中的 TDI 技术

【探测器】线阵相机中的 TDI 技术 1.背景2.TDI相机3.场景应用 1.背景 TDI 即Time Delay Integration时间延迟积分。 TDI相机是线阵相机的一种特殊类型&#xff0c;带有独特的时间延迟积分&#xff08;TDI&#xff09;技术。 换句话说&#xff0c;TDI相机是线阵相机的一个高级版…

HCIP-HarmonyOS Application Developer 习题(七)

&#xff08;判断&#xff09;1、HarmonyOs跨端迁移和多端协同&#xff0c;是使用不同的FA/PA&#xff0c;在不同设备间运行来实现完整的业务。 答案&#xff1a;错误 分析&#xff1a; &#xff08;判断&#xff09;2、HarmonyOs的方舟开发框架包含基于TS扩展的类Web开发范式…

【RPC】—Thrift协议 VS Protobuf

Thrift协议 & VS Protobuf ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记仓库&#x1f449;https://github.com/A-BigTree/tree-learning-notes 个人主页&#x1f449;https://www.abigtree.top ⭐⭐⭐⭐⭐⭐ 文章目录 Thrift协议 & VS Pro…

云原生(四十九) | WordPress源码部署

文章目录 WordPress源码部署 一、WordPress部署步骤 二、创建项目目录 三、上传源码到WordPress 四、配置安全组 五、配置WordPress 六、访问WordPress WordPress源码部署 一、WordPress部署步骤 第一步&#xff1a;创建项目目录 第二步&#xff1a;上传源码到项目目…

ARM(5)内存管理单元MMU

一、虚拟地址和物理地址 首先&#xff0c;计算机系统的内存被组成一个由M个连续的字节大小组成的数组。每字节都会有一个唯一的物理地址。CPU访问内存最简单的方式就是使用物理地址。如下图&#xff1a; 图 1 物理地址,物理寻址 而现在都是采用的都是虚拟寻址的方法。CPU生成一…

51单片机的自动制冷系统【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温度传感器继电器LED、按键和蜂鸣器等模块构成。适用于车载便携式自动制冷系统、冰箱制冷、温度控制等相似项目。 可实现功能: 1、LCD1602实时显示当前温度 2、温度传感器DS18B20采集温度 3、按键可设置温度的阈…

【开发心得】筑梦上海:项目风云录(6)

目录 会海跳槽 票务开启 漂泊在外的日子 未完待续 会海跳槽 随着时刻表的出炉&#xff0c;意味着大规模的界面开发逐步进入正规。项目组里陆陆续续引进了8个人&#xff0c;最多的时候&#xff0c;同时有10个人在现场。“松工”为我们准备的办公室坐的满满当当&#xff0c;…

攸信动态丨厦门火炬大学堂携手厦门攸信技术,共探盈趣汽车电子数字化转型标杆之路

今日上午&#xff0c;在厦门市工信局指导下&#xff0c;由厦门盈趣汽车电子有限公司、厦门攸信信息技术有限公司携手北京赛昇科技有限公司与厦门火炬大学堂联合举办的“厦门中小企业数字化转型人才培训&#xff08;第14期&#xff09;”活动&#xff0c;在热烈而充实的氛围中圆…

gitlab-ci 集成 k3s 部署spring boot 应用

环境 一台ECS gitlab 16.10 一台ECS gitlab-runner docker方式 一台腾讯云服务器 k3s k3s version v1.30.5k3s1 (9b586704) go version go1.22.6 本地: idea 2024 准备开始 gitlab上创建"api"仓库,本地IDEA 创建spring boot web demo项目k8s-gitlab-demo. 确保能…

手把手带你服务端实现支付功能的通用解决方案!(全网最新)

友情提示&#xff1a; 跳转到本人juejin观看体验更佳&#xff08;当然CSDN也很好&#x1f60b;&#xff09; link —> https://juejin.cn/user/679936123997707/posts Thanks!&#x1f339; 前言 前段时间&#xff0c;和朋友们一起搭建的一个网站需要实现支付功能&#xff…

速卖通、Shopee、Lazada自养号测评的五大关键步骤:从环境构建到风控应对

在跨境电商领域&#xff0c;速卖通、Shopee和Lazada等平台上的自养号测评已成为提升销量、优化产品排名的重要手段。自养号测评不仅能够帮助卖家快速积累好评&#xff0c;还能有效提升产品的曝光率和转化率。然而&#xff0c;自养号测评并非易事&#xff0c;需要掌握一系列专业…

软考UML图 -- ( 类图,对象图,用例图,序列图,通信图,状态图,活动图,构件图,部署图)

文章目录 一、UML统一建模语言二、关系三、UML图1. 类图2. 对象图3. 用例图4. 序列图&#xff08;顺序图&#xff09;—— 交互图5. 通信图 —— 交互图6. 状态图7. 活动图8. 构件图&#xff08;组件图&#xff09;9. 部署图10. 总结 一、UML统一建模语言 UML由3个要素构成:UM…

Linux 外设驱动 应用 1 IO口输出

从这里开始外设驱动介绍&#xff0c;这里使用的IMX8的芯片作为驱动介绍 开发流程&#xff1a; 修改设备树&#xff0c;配置 GPIO1_IO07 为 GPIO 输出。使用 sysfs 接口或编写驱动程序控制 GPIO 引脚。编译并测试。 这里假设设备树&#xff0c;已经配置好了。不在论述这个问题…