额外题目汇总2-链表
链表
1.24. 两两交换链表中的节点
力扣题目链接(opens new window)
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路
使用虚拟头结点会很方便,要不每次针对头结点(没有前一个指针指向头结点),还要单独处理。
链表:听说用虚拟头节点会方便很多? (opens new window)。
接下来就是交换相邻两个元素
初始时,cur指向虚拟头结点,然后进行如下三步:
操作之后,链表如下:
看这个可能就更直观一些了:
public class Swap_Nodes_in_Pairs {public static class ListNode {//ListNode 是一个静态内部类,用于表示链表中的节点。int val;//存储节点的值。ListNode next;//指向下一个节点的引用。public ListNode(int val) {//构造函数,用于创建一个新的节点,并将其值初始化为传入的参数 val。this.val = val;}}public ListNode swapPairs3(ListNode head) {ListNode dummy = new ListNode(0);//创建一个值为 0 的虚拟头节点 dummy。虚拟头节点的引入能够统一处理链表头节点的交换情况,避免了对头节点进行特殊处理的复杂性。dummy.next = head;//把虚拟头节点的 next 指针指向原链表的头节点 head,从而将虚拟头节点接入到原链表中。ListNode cur = dummy;//创建一个指针 cur 并初始化为虚拟头节点,后续会使用这个指针来遍历链表。while (cur.next != null && cur.next.next != null) {//保证了当前 cur 节点后面至少存在两个节点,这样才能进行节点的两两交换。ListNode node1 = cur.next; //要交换的两个节点中的第一个节点。ListNode node2 = cur.next.next;//要交换的两个节点中的第二个节点。cur.next = node2;//实现了当前节点跳过 node1 直接指向 node2。node1.next = node2.next;//第 1 个节点指向第 2 个节点的下一个节点node2.next = node1; //把 node2 的 next 指针指向 node1,完成了 node1 和 node2 两个节点的交换。cur = cur.next.next;//将 cur 指针移动到当前交换完成的节点对的下一个节点对的前一个节点位置,为下一轮的节点交换做准备。}return dummy.next;//当循环结束后,链表中所有相邻的节点对都已经完成了交换操作。由于虚拟头节点的 next 指针指向的就是交换后的链表头节点,所以直接返回 dummy.next。}
}
时间复杂度
我们遍历链表一次,每次处理两个节点。由于每个节点只被访问一次,因此时间复杂度为 O(n),其中 n 是链表中节点的数量。
空间复杂度
该方法只使用了常量级别的额外空间来存储指针(如 dummy
, cur
, node1
, node2
),并没有使用任何额外的数据结构来存储节点。因此,空间复杂度为 O(1)。
时间复杂度:O(n)
空间复杂度:O(1)
链表 1 -> 2 -> 3 -> 4
1. 初始化
- 创建一个虚拟头节点
dummy
,其值为0
。 - 将
dummy
的next
指针指向原链表的头节点head
(这里head
指向节点1
)。 - 初始化指针
cur
指向虚拟头节点dummy
。
此时链表结构如下(dummy
为虚拟头节点):
dummy(0) -> 1 -> 2 -> 3 -> 4^cur
2. 第一次交换(处理节点 1
和 2
)
- 获取要交换的节点:
ListNode node1 = cur.next;
:node1
指向节点1
。ListNode node2 = cur.next.next;
:node2
指向节点2
。
- 交换节点:
cur.next = node2;
:让cur
(即dummy
)的next
指针指向node2
(节点2
)。node1.next = node2.next;
:让node1
(节点1
)的next
指针指向node2
的下一个节点(节点3
)。node2.next = node1;
:让node2
(节点2
)的next
指针指向node1
(节点1
)。
交换后链表结构变为:
dummy(0) -> 2 -> 1 -> 3 -> 4^cur
- 移动指针:
cur = cur.next.next;
:将cur
指针移动到当前交换完成的节点对(2 -> 1
)的下一个节点对的前一个节点(节点1
)。
3. 第二次交换(处理节点 3
和 4
)
此时 cur
指向节点 1
,继续循环:
- 获取要交换的节点:
ListNode node1 = cur.next;
:node1
指向节点3
。ListNode node2 = cur.next.next;
:node2
指向节点4
。
- 交换节点:
cur.next = node2;
:让cur
(节点1
)的next
指针指向node2
(节点4
)。node1.next = node2.next;
:让node1
(节点3
)的next
指针指向node2
的下一个节点(这里为null
)。node2.next = node1;
:让node2
(节点4
)的next
指针指向node1
(节点3
)。
交换后链表结构变为:
dummy(0) -> 2 -> 1 -> 4 -> 3 -> null^cur
- 移动指针:
cur = cur.next.next;
:将cur
指针移动到当前交换完成的节点对(4 -> 3
)的下一个节点对的前一个节点,但此时cur.next == null
,不满足循环条件,循环结束。
4. 返回结果
由于 dummy.next
指向节点 2
,所以最终返回交换后的链表 2 -> 1 -> 4 -> 3
。
2.234.回文链表
力扣题目链接(opens new window)
请判断一个链表是否为回文链表。
示例 1:
- 输入: 1->2
- 输出: false
示例 2:
- 输入: 1->2->2->1
- 输出: true
思路
数组模拟
最直接的想法,就是把链表装成数组,然后再判断是否回文。
反转后半部分链表
分为如下几步:
- 用快慢指针,快指针有两步,慢指针走一步,快指针遇到终止位置时,慢指针就在链表中间位置
- 同时用pre记录慢指针指向节点的前一个节点,用来分割链表
- 将链表分为前后均等两部分,如果链表长度是奇数,那么后半部分多一个节点
- 将后半部分反转 ,得cur2,前半部分为cur1
- 按照cur1的长度,一次比较cur1和cur2的节点数值
如图所示:
public class Palindrome_Linked_List {public static class ListNode {//ListNode 是一个静态内部类,用于表示链表中的节点。int val;//存储节点的值。ListNode next;//指向下一个节点的引用。public ListNode(int i) {this.val = i;}}public boolean isPalindrome1(ListNode head) {int len = 0;//初始化一个整型变量 len 用于记录链表的长度,初始值为 0。ListNode cur = head;//创建一个指针 cur 并将其指向链表的头节点 head,用于遍历链表。while (cur != null) {//while 循环遍历链表,只要 cur 不为 null,就表示还没有遍历到链表的末尾。len++;//每遍历一个节点,就将 len 的值加 1。cur = cur.next;//将 cur 指针移动到下一个节点。}cur = head;//将 cur 指针重新指向链表的头节点,为将链表元素存储到数组做准备。int[] res = new int[len];//创建一个长度为 len 的整型数组 res,用于存储链表中的元素。for (int i = 0; i < res.length; i++){//for 循环遍历数组,将链表中的元素依次存储到数组中。res[i] = cur.val;//将当前 cur 指针所指向节点的值存储到数组的第 i 个位置。cur = cur.next;//将 cur 指针移动到下一个节点。}for (int i = 0, j = len - 1; i < j; i++, j--){//使用双指针法,i 从数组的起始位置开始,j 从数组的末尾位置开始,向中间移动。只要 i < j,就表示还没有比较完所有对称位置的元素。if (res[i] != res[j]){//如果数组中对称位置的元素不相等,说明链表不是回文链表,直接返回 false。return false;}}return true;//如果循环结束后都没有发现不相等的元素,说明链表是回文链表,返回 true。}
}
时间复杂度
1. 计算链表长度:我们遍历链表一次以计算长度,时间复杂度为 O(n),其中 \(n\) 是链表的节点数。
2. 存储链表元素到数组:我们再次遍历链表,将元素存储到数组中,时间复杂度也是 O(n)。
3. 比较数组元素:最后,我们进行一次比较,时间复杂度为 O(n/2)(因为只需比较一半的元素),但在大O表示法中,常数因子通常被省略,因此这部分的时间复杂度也是 O(n)。 综合以上步骤,总的时间复杂度为 O(n)。
空间复杂度
1. 数组存储:我们创建了一个长度为 n 的整型数组来存储链表的元素,因此空间复杂度为 O(n)。 2. 其他变量:除了数组外,使用的其他变量(如指针和整型变量)占用的空间是常数级别的O(1)。 因此,总的空间复杂度为 O(n)。
时间复杂度: O(n)
空间复杂度: O(n)
1 -> 2 -> 2 -> 1
1. 初始化变量
len
初始化为 0,用于记录链表的长度。cur
指针初始化为指向链表的头节点head
,这里head
指向值为 1 的节点。
此时链表结构如下:
1 -> 2 -> 2 -> 1
^
cur
2. 统计链表长度
- 第一次循环:
cur
指向值为 1 的节点,len
加 1 变为 1,cur
移动到下一个节点(值为 2 的节点)。 - 第二次循环:
cur
指向值为 2 的节点,len
加 1 变为 2,cur
移动到下一个节点(另一个值为 2 的节点)。 - 第三次循环:
cur
指向值为 2 的节点,len
加 1 变为 3,cur
移动到下一个节点(值为 1 的节点)。 - 第四次循环:
cur
指向值为 1 的节点,len
加 1 变为 4,cur
移动到null
,循环结束。
此时得到链表长度 len = 4
。
3. 将链表元素存储到数组中
cur
重新指向链表的头节点(值为 1 的节点)。- 创建长度为 4 的整型数组
res
。 - 第一次循环:
i = 0
,res[0]
赋值为cur
指向节点的值 1,cur
移动到下一个节点(值为 2 的节点)。 - 第二次循环:
i = 1
,res[1]
赋值为cur
指向节点的值 2,cur
移动到下一个节点(另一个值为 2 的节点)。 - 第三次循环:
i = 2
,res[2]
赋值为cur
指向节点的值 2,cur
移动到下一个节点(值为 1 的节点)。 - 第四次循环:
i = 3
,res[3]
赋值为cur
指向节点的值 1,cur
移动到null
,循环结束。
此时数组 res
中的元素为 [1, 2, 2, 1]
。
4. 使用双指针法比较数组对称位置的元素
- 第一次比较:
i = 0
,j = 3
,res[0] = 1
,res[3] = 1
,两者相等,继续循环。 - 第二次比较:
i = 1
,j = 2
,res[1] = 2
,res[2] = 2
,两者相等,继续循环。 - 此时
i = 2
,j = 1
,不满足i < j
的条件,循环结束。
5. 返回结果
由于在比较过程中没有发现不相等的元素,所以判断该链表是回文链表,返回 true
。
3.143.重排链表
力扣题目链接(opens new window)
- 数组模拟
把链表放进数组中,然后通过双指针法,一前一后,来遍历数组,构造链表。
- 双向队列模拟
把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表。
- 直接分割链表
将链表分割成两个链表,然后把第二个链表反转,之后在通过两个链表拼接成新的链表。
如图:
public class Reorder_List {public static class ListNode {//ListNode 是一个静态内部类,用于表示链表中的节点。int val;//存储节点的值。ListNode next;//指向下一个节点的引用。public ListNode(int i) {this.val = i;}}public void reorderList2(ListNode head) {Deque<ListNode> de = new LinkedList<>();//双端队列允许在队列的两端进行插入和删除操作ListNode cur = head.next;//指针 cur 并将其指向链表头节点的下一个节点,因为头节点 L0 不需要存入队列,后续会作为重排后链表的起始节点。while (cur != null){//while 循环遍历链表,只要 cur 不为 null,就表示还未遍历到链表末尾。de.offer(cur);//将当前节点 cur 加入到双端队列 de 的尾部。cur = cur.next;//将 cur 指针移动到下一个节点。}cur = head;//重新指向链表的头节点int count = 0;//用于记录当前选取节点的次数while (!de.isEmpty()){//只要双端队列 de 不为空,说明还有节点需要处理,继续循环。if (count % 2 == 0){//当 count 为偶数时,从双端队列 de 的尾部取出一个节点,将 cur 的 next 指针指向该节点,pollLast() 方法会移除并返回队列的最后一个元素。cur.next = de.pollLast();}else {//当 count 为奇数时,从双端队列 de 的头部取出一个节点,将 cur 的 next 指针指向该节点,poll() 方法会移除并返回队列的第一个元素。cur.next = de.poll();}cur = cur.next;//将 cur 指针移动到新连接的节点,以便进行下一次连接操作。count++;//count 加 1,记录选取节点的次数。}cur.next = null;//当双端队列 de 为空时,循环结束,此时链表重排基本完成。但最后一个节点的 next 指针可能仍然指向原链表中的某个节点,为了确保链表正确结束,将 cur 的 next 指针置为 null。}
}
时间复杂度
1. 构建双端队列: 方法首先遍历链表,将所有节点(除了头节点)加入到双端队列中。这一遍历的时间复杂度为 O(n),其中n是链表中的节点数。
2. 重排链表: 接下来,方法进入一个循环,直到双端队列为空。在每次迭代中,它从队列的头部或尾部取出一个节点,并将其链接到新的链表中。由于每个节点只处理一次,这部分的时间复杂度也是 O(n)。 综合以上两个步骤,整体的时间复杂度为:O(n) + O(n) = O(n)
空间复杂度
1. 双端队列的存储: 方法使用一个双端队列来存储所有节点(除了头节点)。在最坏的情况下,这意味着需要存储 n-1个节点,因此空间复杂度为 O(n)。
2. 其他变量: 方法使用了一些额外的变量(如 cur
和 count
),这些变量占用的空间是常数级别的 O(1)。 因此,总的空间复杂度主要由双端队列的存储决定:O(n)
时间复杂度:O(n)
空间复杂度:O(n)
1 -> 2 -> 3 -> 4 -> 5
1. 初始化双端队列并存储节点
de
是一个双端队列,用于存储链表中除头节点外的所有节点。cur
初始化为head.next
,即指向节点2
。- 开始遍历链表:
- 第一次循环:
cur
指向节点2
,将节点2
加入双端队列de
的尾部,然后cur
移动到节点3
。 - 第二次循环:
cur
指向节点3
,将节点3
加入双端队列de
的尾部,然后cur
移动到节点4
。 - 第三次循环:
cur
指向节点4
,将节点4
加入双端队列de
的尾部,然后cur
移动到节点5
。 - 第四次循环:
cur
指向节点5
,将节点5
加入双端队列de
的尾部,然后cur
移动到null
,循环结束。
- 第一次循环:
此时,双端队列 de
中的元素依次为 [2, 3, 4, 5]
。
2. 重新定位指针并初始化计数器
cur
重新指向链表的头节点,即节点1
。count
初始化为0
,用于记录当前选取节点的次数。
3. 按规则重排链表
- 第一次循环(
count = 0
,偶数):cur
指向节点1
,从双端队列de
的尾部取出节点5
,将cur
(节点1
)的next
指针指向节点5
。cur
移动到节点5
,count
加 1 变为1
。此时双端队列de
中的元素为[2, 3, 4]
。
- 第二次循环(
count = 1
,奇数):cur
指向节点5
,从双端队列de
的头部取出节点2
,将cur
(节点5
)的next
指针指向节点2
。cur
移动到节点2
,count
加 1 变为2
。此时双端队列de
中的元素为[3, 4]
。
- 第三次循环(
count = 2
,偶数):cur
指向节点2
,从双端队列de
的尾部取出节点4
,将cur
(节点2
)的next
指针指向节点4
。cur
移动到节点4
,count
加 1 变为3
。此时双端队列de
中的元素为[3]
。
- 第四次循环(
count = 3
,奇数):cur
指向节点4
,从双端队列de
的头部取出节点3
,将cur
(节点4
)的next
指针指向节点3
。cur
移动到节点3
,count
加 1 变为4
。此时双端队列de
为空。
4. 处理链表结尾
此时,双端队列 de
为空,循环结束。将 cur
(节点 3
)的 next
指针置为 null
,确保链表正确结束。
最终重排后的链表为 1 -> 5 -> 2 -> 4 -> 3
。
4.141. 环形链表
力扣题目链接(opens new window)
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
思路
使用快慢指针法, 分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。
为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢?
首先第一点: fast指针一定先进入环中,如果fast 指针和slow指针相遇的话,一定是在环中相遇。
为什么fast指针和slow指针一定会相遇呢?
可以画一个环,然后让 fast指针在任意一个节点开始追赶slow指针。
会发现最终都是这种情况, 如下图:
fast和slow各自再走一步, fast和slow就相遇了
这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。
动画如下:
public class Circular_Linked_List {public static class ListNode {//ListNode 是一个静态内部类,用于表示链表中的节点。int val;//存储节点的值。ListNode next;//指向下一个节点的引用。public ListNode(int i) {this.val = i;}}public boolean hasCycle(ListNode head) {ListNode fast = head;//fast 和 slow 指针都初始化为指向链表的头节点 head。fast 指针后续会以每次移动两步的速度遍历链表,slow 指针则以每次移动一步的速度遍历链表。ListNode slow = head;// 空链表、单节点链表一定不会有环while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (fast == slow) { // 快慢指针相遇,表明有环return true;}}return false; // 正常走到链表末尾,表明没有环}
}
时间复杂度
在最坏的情况下,快慢指针会遍历整个链表。快指针每次移动两步,慢指针每次移动一步,因此最多会遍历 n 个节点,时间复杂度为 O(n)。
空间复杂度
只使用了常量级别的额外空间(即两个指针 fast
和 slow
),不随输入规模的变化而变化,因此空间复杂度为 O(1)。
总结而言,这段代码的时间复杂度为 O(n),空间复杂度为 O(1)。
无环链表 1 -> 2 -> 3 -> 4
初始化:fast 和 slow 指针都指向节点 1。
第一次循环:
fast 指针移动两步,指向节点 3(1 -> 2 -> 3)。
slow 指针移动一步,指向节点 2(1 -> 2)。
此时 fast 不等于 slow,继续循环。
第二次循环:
fast 指针尝试再移动两步,但由于节点 4 的 next 为 null,fast.next.next 会导致 fast 变为 null,不满足 while 循环条件(fast != null && fast.next != null),循环结束。
返回结果:由于循环正常结束,说明链表没有环,返回 false。
有环链表 1 -> 2 -> 3 -> 4
初始化:fast 和 slow 指针都指向节点 1。
第一次循环:
fast 指针移动两步,指向节点 3(1 -> 2 -> 3)。
slow 指针移动一步,指向节点 2(1 -> 2)。
此时 fast 不等于 slow,继续循环。
第二次循环:
fast 指针移动两步,由于存在环,节点 4 的 next 指向节点 2,所以 fast 指向节点 2(3 -> 4 -> 2)。
slow 指针移动一步,指向节点 3(2 -> 3)。
此时 fast 不等于 slow,继续循环。
第三次循环:
fast 指针移动两步,指向节点 4(2 -> 3 -> 4)。
slow 指针移动一步,指向节点 4(3 -> 4)。
此时 fast 等于 slow,满足 if 条件,返回 true,表示链表有环。
5.面试题 02.07. 链表相交
同:160.链表相交
力扣题目链接(opens new window)
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
示例 2:
示例 3:
思路
求两个链表交点节点的指针。 交点不是数值相等,而是指针相等。
为了方便举例,假设节点元素数值相等,则节点指针相等。
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。否则循环退出返回空指针。
public class Intersection_of_Two_Linked_Lists {public static class ListNode {//ListNode 是一个静态内部类,用于表示链表中的节点。int val;//存储节点的值。ListNode next;//指向下一个节点的引用。public ListNode(int i) {this.val = i;}}public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {ListNode p1 = headA, p2 = headB;//p1 初始化为指向链表 headA 的头节点,p2 初始化为指向链表 headB 的头节点。while (p1 != p2) {//只要 p1 和 p2 不指向同一个节点,就继续循环。当 p1 和 p2 相等时,有两种情况:一是找到了相交节点,二是两个链表不相交,此时 p1 和 p2 都为 null。if (p1 == null) {//如果 p1 为 null,说明 p1 已经遍历完链表 headA,将 p1 重新指向链表 headB 的头节点,开始遍历链表 headB。p1 = headB;} else {//否则,将 p1 移动到下一个节点,p1 = p1.next;}if (p2 == null) {//如果 p2 为 null,说明 p2 已经遍历完链表 headB,将 p2 重新指向链表 headA 的头节点,开始遍历链表 headA。p2 = headA;} else {//否则,将 p2 移动到下一个节点p2 = p2.next;}}return p1;//当 while 循环结束时,p1 和 p2 相等。如果两个链表相交,p1 指向的就是相交节点;如果两个链表不相交,p1 和 p2 最终都会遍历完两个链表,同时指向 null,所以返回 p1}
}
时间复杂度
在最坏的情况下,指针 p1
和 p2
会遍历两个链表的所有节点。这里 n
是链表 A 的长度, m
是链表 B 的长度。因此,时间复杂度为 O(n + m)。
空间复杂度
该算法只使用了固定数量的额外空间,即两个指针 p1
和 p2
,不随输入规模的变化而变化。因此,空间复杂度为 O(1)。
时间复杂度:O(n + m)
空间复杂度:O(1)
示例 1:两个链表相交
假设存在两个相交链表:
链表 headA:1 -> 2 -> 3 -> 6 -> 7
链表 headB:4 -> 5 -> 6 -> 7
两个链表在节点 6 处相交。
-
初始化:
-
p1
指向链表headA
的头节点1
。 -
p2
指向链表headB
的头节点4
。
-
-
第一次遍历:
-
p1
依次经过节点1
、2
、3
、6
、7
,然后p1
变为null
,根据逻辑将p1
重新指向链表headB
的头节点4
。 -
p2
依次经过节点4
、5
、6
、7
,然后p2
变为null
,根据逻辑将p2
重新指向链表headA
的头节点1
。
-
-
第二次遍历:
-
p1
从节点4
开始,经过节点5
,到达节点6
。 -
p2
从节点1
开始,经过节点2
、3
,到达节点6
。此时p1
和p2
相等,while
循环结束。
-
-
返回结果:返回
p1
,即节点6
,这就是两个链表的相交节点。
示例 2:两个链表不相交
假设存在两个不相交链表:
- 链表
headA
:1 -> 2 -> 3
- 链表
headB
:4 -> 5
初始化:
p1 指向链表 headA 的头节点 1。
p2 指向链表 headB 的头节点 4。
第一次遍历:
p1 依次经过节点 1、2、3,然后 p1 变为 null,根据逻辑将 p1 重新指向链表 headB 的头节点 4。
p2 依次经过节点 4、5,然后 p2 变为 null,根据逻辑将 p2 重新指向链表 headA 的头节点 1。
第二次遍历:
p1 从节点 4 开始,经过节点 5,然后 p1 又变为 null。
p2 从节点 1 开始,经过节点 2、3,然后 p2 也变为 null。此时 p1 和 p2 相等且都为 null,while 循环结束。
返回结果:返回 p1,即 null,表示两个链表不相交。
相关文章:

额外题目汇总2-链表
链表 1.24. 两两交换链表中的节点 力扣题目链接(opens new window) 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 思路 使用虚拟头结点会很方便ÿ…...

C#控件开发6—指示灯
按钮功能:手自动旋转,标签文本显示、点击二次弹框确认(源码在最后边); 【制作方法】 找到控件的中心坐标,画背景外环、内圆;再绘制矩形开关,进行角度旋转即可获得; 【关…...

探索从传统检索增强生成(RAG)到缓存增强生成(CAG)的转变
在人工智能快速发展的当下,大型语言模型(LLMs)已成为众多应用的核心技术。检索增强生成(RAG)(RAG 系统从 POC 到生产应用:全面解析与实践指南)和缓存增强生成(CAG&#x…...
【学习总结|DAY036】Vue工程化+ElementPlus
引言 在前端开发领域,Vue 作为一款流行的 JavaScript 框架,结合 ElementPlus 组件库,为开发者提供了强大的构建用户界面的能力。本文将结合学习内容,详细介绍 Vue 工程化开发流程以及 ElementPlus 的使用,助力开发者快…...

【GitHub】GitHub 2FA 双因素认证 ( 使用 Microsoft Authenticator 应用进行二次验证 )
文章目录 一、GitHub 的 2FA 双因素认证二、使用 Microsoft Authenticator 应用进行二次验证1、TOTP 应用2、下载 Microsoft Authenticator 应用3、安装使用 Authenticator 应用 三、恢复码重要性 一、GitHub 的 2FA 双因素认证 现在登录 GitHub 需要进行二次身份验证 ; 先登录…...
c# 2025/2/7 周五
13.《表达式,语句详解1》 18未完。。 表达式,语句详解_1_哔哩哔哩_bilibili...

蓝桥杯思维训练(五)
文章目录 子集II1191.K次串联后最大子数组之和 子集II 子集II 思路分析: 求解子集的问题的关键就是,通过递归与回溯,我们就是得确定以某个元素开始的子集,对于这个题目来说,比较麻烦的一点就是,存在重复的…...

I.MX6ULL 中断介绍下
GIC重点寄存器 1.中断分发器寄存器(Distributor register ) a.Distributor Control Register(中断分发控制寄存器), GICD_CTLR Purpose Enables the forwarding of pending interrupts from the Distributor to the CPU interfaces 使能将挂起的中断从…...
Elasticsearch 生产集群部署终极方案
Elasticsearch 集群部署 1.集群部署1.1 新增用户1.2 优化操作系统1.3 JDK1.4 elasticsearch1.5 开机自启动 2.安全认证功能2.1 生成CA证书2.2 生成密钥2.3 上传至其他节点2.4 修改属主、属组2.5 配置文件添加参数2.6 各节点添加密钥库密码2.7 设置用户密码 1.集群部署 1.1 新增…...

Python用langchain、OpenAI大语言模型LLM情感分析苹果股票新闻数据及提示工程优化应用...
全文链接:https://tecdat.cn/?p39614 本文主要探讨了如何利用大语言模型(LLMs)进行股票分析。通过使用提供的股票市场和金融新闻获取数据,结合Python中的相关库,如Pandas、langchain等,实现对股票新闻的情…...

【正点原子K210连载】第六十七章 音频FFT实验 摘自【正点原子】DNK210使用指南-CanMV版指南
第六十七章 音频FFT实验 本章将介绍CanMV下FFT的应用,通过将时域采集到的音频数据通过FFT为频域。通过本章的学习,读者将学习到CanMV下控制FFT加速器进行FFT的使用。 本章分为如下几个小节: 32.1 maix.FFT模块介绍 32.2 硬件设计 32.3 程序设…...

Centos Ollama + Deepseek-r1+Chatbox运行环境搭建
Centos Ollama Deepseek-r1Chatbox运行环境搭建 内容介绍下载ollama在Ollama运行DeepSeek-r1模型使用chatbox连接ollama api 内容介绍 你好! 这篇文章简单讲述一下如何在linux环境搭建 Ollama Deepseek-r1。并在本地安装的Chatbox中进行远程调用 下载ollama 登…...

ReactNative进阶(五十九):存量 react-native 项目适配 HarmonyOS NEXT
文章目录 一、前言二、ohos_react_native2.1 Fabric2.2 TurboModule2.2.1 ArkTSTurboModule2.2.2 cxxTurboModule: 三、拓展阅读 一、前言 2024年10月22日19:00,华为在深圳举办“原生鸿蒙之夜暨华为全场景新品发布会”,主题为“星河璀璨&…...

go并发和并行
进程和线程 进程(Process)就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位,进程是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间。…...

一种解决SoC总线功能验证完备性的技术
1. 前言 通过总线将各个IP通过总线连接起来的SoC芯片是未来的大趋势,也是缩短芯片开发周期,抢先进入市场的常用方法。如何确保各个IP是否正确连接到总线上,而且各IP的地址空间分配是否正确,是一件很棘手的事情。本文提出了一种新…...

Web3 与区块链:开启透明、安全的网络新时代
在这个信息爆炸的时代,我们对网络的透明性、安全性和隐私保护的需求日益增长。Web3,作为新一代互联网的代表,正携手区块链技术,引领我们走向一个更加透明、安全和去中心化的网络世界。本文将深入探讨 Web3 的基本概念、区块链技术…...
c#中Thread.Join()方法的经典示例
在 C# 中,Thread.Join 是一个非常有用的方法,它可以让主线程(调用线程)等待子线程(被调用线程)执行完毕后再继续执行。 1、经典示例1 using System; using System.Threading;public class Example {stati…...

深入了解越权漏洞:概念、危害与防范
前言 越权漏洞作为一种常见且极具威胁的安全隐患,就像隐藏在暗处的 “黑客帮凶”,时刻威胁着我们的数据安全和隐私。就让我们一起揭开越权漏洞的神秘面纱,深入了解它的来龙去脉、危害以及应对之策。 一、什么是越权漏洞 想象一下࿰…...

MySQL 数据库编程-C++
目录 1 数据库基本知识 1.1 MYSQL常见命令 1.2 SQL注入 1.3 ORM框架 1 数据库基本知识 MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念, 一个关系型数据库由一个或数个表格组成:…...

dl学习笔记(9):pytorch数据处理的完整流程
1)自动导入常用库的设置方式 在开始之前,这里介绍一下自动导入常用的你需要加载的库的操作方式。 首先在我们的目录下找到ipython文件,如下图: 然后找到里面的startup文件: 然后新建一个文本文档,输入你每…...

联想拯救者R9000P 网卡 Realtek 8852CE Ubuntu/Mint linux 系统睡眠后,无线网卡失效
联想拯救者R9000P 网卡型号 Realtek PCle GbE Family Controller Realtek 8852CE WiFi 6E PCI-E NIC 系统版本 Ubuntu 24.04 / mint 22.1 问题现象 rtw89_8852ce,Link is Down,xtal si not ready,mac init fail,xtal si not …...
GaLore:基于梯度低秩投影的大语言模型高效训练方法详解一
📘 GaLore:基于梯度低秩投影的大语言模型高效训练方法详解 一、论文背景与动机 随着大语言模型(LLM)参数规模的不断增长,例如 GPT-3(175B)、LLaMA(65B)、Qwenÿ…...
SpringBoot3项目架构设计与模块解析
一、项目概述 这是一个基于SpringBoot3构建的企业级后台管理系统,从项目结构来看,系统采用了经典的分层架构设计,包含完整的控制器层、服务层、数据访问层和实体层。项目整合了Web开发、数据库访问、权限控制等核心功能模块。 二、项目整体…...
【PmHub面试篇】性能监控与分布式追踪利器Skywalking面试专题分析
你好,欢迎来到本次关于PmHub整合性能监控与分布式追踪利器Skywalking的面试系列分享。在这篇文章中,我们将深入探讨这一技术领域的相关面试题预测。若想对相关内容有更透彻的理解,强烈推荐参考之前发布的博文:【PmHub后端篇】Skyw…...

上门预约行业技术方案全解析:小程序、App还是H5?如何选择?
上门按摩行业这几年确实火,但千万别以为随便买个系统、招几个技师就能赚钱。作为一家深耕10年软件开发的公司,我们做了四五年上门按摩系统,见过太多人头脑一热冲进来,结果血本无归。 如果你真的想做上门按摩,先想清楚这…...
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战
使用WebSocket实时获取印度股票数据源(无调用次数限制)实战 一、前置准备 1. 获取API密钥 登录 StockTV开发者平台 → 联系客服获取测试Key(格式MY4b781f618e3f43c4b055f25fa61941ad),该密钥无调用次数限制且支持实时…...

新华三H3CNE网络工程师认证—Easy IP
Easy IP 就是“用路由器自己的公网IP,给全家所有设备当共享门牌号”的技术!(省掉额外公网IP,省钱又省配置!) 生活场景对比,想象你住在一个小区:普通动态NAT:物业申请了 …...

命令行以TLS/SSL显式加密方式访问FTP服务器
昨天留了一个小尾巴~~就是在命令行或者代码调用命令,以TLS/SSL显式加密方式,访问FTP服务器,上传和下载文件。 有小伙伴可能说ftp命令不可以吗?不可以哦~~ ftp 命令本身不支持显式加密。要实现 FTP 的显式加密,可以使…...

v1.0.1版本更新·2025年5月22日发布-优雅草星云物联网AI智控系统
v1.0.1版本更新2025年5月22日发布-优雅草星云物联网AI智控系统 开源地址 星云智控官网: 优雅草星云物联网AI智控软件-移动端vue: 优雅草星云物联网AI智控软件-移动端vue 星云智控PC端开源: 优雅草星云物联网AI智控软件-PC端vue: 优雅草星云物联网AI…...
Python使用总结之Mac安装docker并配置wechaty
Python使用总结之Mac安装docker并配置wechaty ✅ 一、安装 Docker Desktop for macOS 1. 下载 Docker Desktop 安装包 访问官网下载安装包: 👉 https://www.docker.com/products/docker-desktop 选择 macOS (Apple 芯片或 Intel 芯片) 版本下载。 …...