LinkedList与链表
ArrayList的缺陷
在上一篇博客中,小编已经较为详细得给大家介绍了ArrayList这个结构了。但是ArrayList存在一些缺陷:由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。
因此:java集合中又引入了LinkedList,即链表结构
链表
链表的概念及结构
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
双向 单向、带头 不带头、循环 不循环
我们主要学习:单向不带头非循环、双向不带头非循环
链表的实现
这里就是自己在写一些链表的方法的时候,自己动手实现一下,感受一下这个链表的内部结构。
代码展示:
package LinkedList;public class MySingleList {// 这里提供一个内部类static class ListNode{public int val; //节点的值域public ListNode next; // 下一个节点的地址// 这里提供一个构造方法public ListNode(int val){this.val = val;}}public ListNode head; // 表示当前链表的头节点/*** 提供一个方法进行链表的初始化*/public void createList(){ListNode node1 = new ListNode(12);ListNode node2 = new ListNode(34);ListNode node3 = new ListNode(45);ListNode node4 = new ListNode(56);ListNode node5 = new ListNode(67);node1.next = node2;node2.next = node3;node3.next = node4;node4.next = node5;this.head = node1;}/*** 下面是一个方法的实现【其实就是增删改查】*///头插法public void addFirst(int data){ListNode node = new ListNode(data);
// // 要考虑列表为空的情况
// if (head == null){
// head = node;
// }node.next = head;head = node;}//尾插法public void addLast(int data){ListNode node = new ListNode(data);// 要考虑列表为空的情况if (head == null){head = node;return;}ListNode curhead = head;while (curhead.next != null){curhead = curhead.next;}curhead.next = node;}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data){ListNode curhead = head;if (index < 0 || index > size()) {System.out.println("您提供的index不合法!");return;}ListNode node = new ListNode(data);// 处理空链表情况if (head == null) {if (index == 0) {head = node;System.out.println("您的列表为空! 直接插入到第一个位置");} else {System.out.println("链表为空,index > 0 无效!");}return;}if (index == 0){addFirst(data);return;}for (int i = 0; i < index-1; i++) {curhead = curhead.next;}node.next = curhead.next;curhead.next = node;}//查找是否包含关键字key是否在单链表当中public boolean contains(int key){// 就默认列表为空就是没有ListNode curhead = head;while (curhead!=null){if (curhead.val == key){return true;}curhead = curhead.next;}return false;}//删除第一次出现关键字为key的节点public void remove(int key){if (head == null) { // 处理空链表return;}// 处理删除头节点的情况if (head.val == key) {head = head.next;return;}ListNode cur = head;while (cur.next != null) { // 遍历链表if (cur.next.val == key) {cur.next = cur.next.next; // 删除当前匹配的节点return; // 只删除第一个匹配项}cur = cur.next;}}//删除所有值为key的节点public void removeAllKey(int key){if (head == null) { // 处理空链表return;}// 处理删除所有头节点为 key 的情况while (head != null && head.val == key) {head = head.next;}// 处理删除中间或尾部的 keyListNode cur = head;while (cur != null && cur.next != null) {if (cur.next.val == key) {cur.next = cur.next.next; // 删除当前匹配的节点} else {cur = cur.next; // 只有当 cur.next 不是 key 时才移动}}}//得到单链表的长度public int size(){int ListSize = 0;ListNode curhead = head;// 来一个语句判断一下链表是否为空while (curhead != null){ListSize++;curhead = curhead.next;}return ListSize; // 如果长度为0【即为空列表即返回这个,告诉用户这是一个空的列表】}// 清空所有链表public void clear() {this.head = null;}// 展示所有列表的数据public void display() {// 进来先判断一下链表是否为空if (head == null){System.out.println("该列表为空!");return;}ListNode curhead = head;while (curhead!=null){System.out.print(curhead.val+" ");curhead = curhead.next;}System.out.println();}}
注:小编这里的代码并不是最优的,只是起一个参考的作用。
测试代码:
package LinkedList;public class Test {public static void main(String[] args) {MySingleList mySingleList = new MySingleList();mySingleList.createList(); // 先把这个初始列表创建出来// 将列表全部展现出来mySingleList.display();// 得到单链表的长度int length = mySingleList.size();System.out.println("单链表的长度为:"+length);// 进行头插mySingleList.addFirst(99);mySingleList.display();// 进行尾插mySingleList.addLast(520);mySingleList.display();// 任意位置插入mySingleList.addIndex(0, 1314);mySingleList.display();mySingleList.addIndex(8, 8989);mySingleList.display();// 查找是否包含关键字key是否在单链表当中boolean result = mySingleList.contains(99);if (result == true){System.out.println("链表中存在这个值!");}else {System.out.println("不好意思!链表中不存在这个值!");}// 删除第一次出现关键字为key的节点mySingleList.addFirst(99);mySingleList.addFirst(99);mySingleList.addLast(99);mySingleList.display();
// mySingleList.remove(99);
// mySingleList.display();//删除所有值为key的节点mySingleList.removeAllKey(99);mySingleList.display();}
}
测试代码不唯一,这里的测试代码也只是起一个参考作用【小编这里的方法代码和测试代码是放到了同一个包里】,大家的代码如果位置不一致,要注意限定修饰符的使用。
链表面试题
1. 删除链表中等于给定值 val 的所有节点。203. 移除链表元素 - 力扣(LeetCode)
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode removeElements(ListNode head, int val) {if (head == null) { // 处理空链表return null;}// 处理删除所有头节点为 key 的情况while (head != null && head.val == val) {head = head.next;}// 处理删除中间或尾部的 keyListNode cur = head;while (cur != null && cur.next != null) {if (cur.next.val == val) {cur.next = cur.next.next; // 删除当前匹配的节点} else {cur = cur.next; // 只有当 cur.next 不是 key 时才移动}}return head;}
}
2. 反转一个单链表.206. 反转链表 - 力扣(LeetCode)
class Solution {public ListNode reverseList(ListNode head) {ListNode cur = head;ListNode pre = null; // 关键修改:pre 应该从 null 开始while (cur != null) {ListNode next = cur.next; // 先保存下一个节点cur.next = pre; // 反转当前节点的指向pre = cur; // 移动 pre 指针cur = next; // 继续遍历}return pre; // 反转后,pre 是新的头节点}
}
3.给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。876. 链表的中间结点 - 力扣(LeetCode)
方法1:算数组长度
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public int size(ListNode head){int ListSize = 0;ListNode curhead = head;// 来一个语句判断一下链表是否为空while (curhead != null){ListSize++;curhead = curhead.next;}return ListSize; // 如果长度为0【即为空列表即返回这个,告诉用户这是一个空的列表】}public ListNode middleNode(ListNode head) {ListNode cur = head;int index = size(head)/2;for(int i = 0; i < index; i++){cur = cur.next;}head = cur;return head;}
}
方法2:快慢指针
快指针都两步,慢指针走一步;当快指针走到末尾的时候,慢指针刚好走到中间位置;
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode middleNode(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;}return slow;}
}
这个代码需要注意的点就是“空指针异常”,在判断循环条件的时候需要多加注意这个逻辑问题。
4. 输入一个链表,输出该链表中倒数第k个结点。
方法一:循环遍历,找到下标
// 1.输入一个链表,输出该链表中倒数第k个结点public int return_val(int k){ListNode cur = head;for (int i = 0; i < size()-k; i++) {cur = cur.next;}return cur.val;}
方法2:快慢指针法
fast先走k-1步;fast和slow再同时走,当fast到终点的时候,slow就刚好到倒数第K个位置。
public ListNode FindthToTail(int k){if (k <= 0 || k > size() || head == null){System.out.println("您提供的下标有误!");return null;}ListNode fast = head;ListNode slow = head;for (int i = 0; i < k-1; i++) {fast = fast.next;}while (fast.next!=null){fast = fast.next;slow = slow.next;}return slow;}
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。21. 合并两个有序链表 - 力扣(LeetCode)
代码示例:
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode headA = list1;ListNode headB = list2;ListNode nh = new ListNode();ListNode th = nh;while(headA!=null && headB!=null){if(headA.val > headB.val){th.next = headB;th = th.next;headB = headB.next;}else{th.next = headA;th = th.next;headA = headA.next;}}if(headA!=null){th.next = headA;}else{th.next = headB;}return nh.next;}
}
6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。链表分割_牛客题霸_牛客网
代码示例:
import java.util.*;/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class Partition {public ListNode partition(ListNode pHead, int x) {// write code hereListNode bs = null;ListNode be = null;ListNode as = null;ListNode ae = null;ListNode cur = pHead;while(cur != null){// 这是第一次插入的情况if(cur.val<x){if(be == null){be = bs = cur;}else{be.next = cur;be = be.next;}}else{if(ae == null){ae = as = cur;}else{ae.next = cur;ae = ae.next;}}cur = cur.next;}// 第一个段没有数据if(be == null){return as;}be.next = as;// 防止最大的数据不是最后一个if(as!=null){ae.next = null; }return bs;}
}
注:在写这个代码的时候,需要注意很多细节类的东西,尤其是一些极端情况,需要多画图看。
7. 链表的回文结构。链表的回文结构_牛客题霸_牛客网
三个步骤:
1.找到链表的中间节点
2.翻转中间节点以后的链表
3.从前/从后开始比较
代码示例:
import java.util.*;/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class PalindromeList {public boolean chkPalindrome(ListNode A) {// 1.找到中间位置// write code hereListNode fast = A;ListNode slow = A;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;}// 2.开始反转ListNode cur = slow.next;ListNode curNext = null;while(cur!=null){curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;}// 3.开始往前往后走while(A!=slow){if(A.val != slow.val){return false;}if(A.next == slow){return true;}A = A.next;slow = slow.next;}return true;}
}
注:上述代码就是前面代码的综合,当我们在写代码的时候,应该考虑到奇数和偶数的不同情况。
8. 输入两个链表,找出它们的第一个公共结点。160. 相交链表 - 力扣(LeetCode)
核心问题:
1.相交是Y字型
2.两个链表长度不一样主要在相交之前
3.可以先让最长链表引用先走他们的差值步
方法1:这个是小编自己画图想出来的方法
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {// 定义一个方法来求列表的长度public int size(ListNode head){int ListSize = 0;ListNode curhead = head;// 来一个语句判断一下链表是否为空while (curhead != null){ListSize++;curhead = curhead.next;}return ListSize; // 如果长度为0【即为空列表即返回这个,告诉用户这是一个空的列表】}public ListNode getIntersectionNode(ListNode headA, ListNode headB) {int ListSizeA = size(headA); // 这是列表A的长度int ListSizeB = size(headB); // 这是列表B的长度// 下面这一步是计算差值,并且先让长的走差值步int Difference = 0;ListNode curA = headA;ListNode curB = headB;if(ListSizeA > ListSizeB){Difference = ListSizeA - ListSizeB;for(int i = 0;i < Difference;i++){curA = curA.next; // 如果列表a长,则先让curA先走差值步}}else{Difference = ListSizeB - ListSizeA;for(int i = 0;i < Difference;i++){curB = curB.next; // 如果列表b长,则先让curB先走差值步}}// 接下来就是一块走了while(curA != null && curB != null){if(curA==curB){return curA;}curA = curA.next;curB = curB.next;}return null;}
}
方法2:由大家补充~
9. 给定一个链表,判断链表中是否有环。 141. 环形链表 - 力扣(LeetCode)
新奇思路:有点类似于操场跑步绕圈,当一个人跑得慢,一个人跑得快,过了一段时间后就会相遇【即有环一定会相遇】
/*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public boolean hasCycle(ListNode head) {if (head == null || head.next == null) {return false;}ListNode slow = head;ListNode fast = head.next;while (fast != null && fast.next != null) {if (fast == slow) {return true; // 快慢指针相遇,说明有环}fast = fast.next.next; // fast 每次走两步slow = slow.next;}return false;}
}
10. 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL.142. 环形链表 II - 力扣(LeetCode)
/*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {// 当我这个列表一个元素都没有的情况下if(head == null){return null;}ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null){fast = fast.next.next; // 快的一下子走两步slow = slow.next; // 慢的一下子走一步if(fast == slow){break; // 退出循环}}if(fast == null || fast.next == null){return null; // 没有环}fast = head;while(fast != slow){fast = fast.next;slow = slow.next;}return fast;}
}
如上述代码中,我们还是依旧是使用快慢指针来进行思路的讲解。所以在链表中,我们要善于使用快慢指针,还同时要注意null的循环条件,是本身不为空,还是下一个不为空。
LinkedList的模拟实现
底层实现的一些底层模拟方法代码:
package double_LinkedList;public class My_double_LinkedList {static class ListNode{public int val;public ListNode pre; // 这个是节点的前驱public ListNode next; // 这个是节点的后继// 这里提供一个内部方法public ListNode(int val){this.val = val;}}// 定义一个头节点public ListNode head;public ListNode last; // 进行尾插法就不需要循环列表了/*** 接下来就是一些模拟实现的方法*///头插法public void addFirst(int data){ListNode node = new ListNode(data); // 先创建一个节点// 如果链表为空if (head == null){head = node; // 此时这个节点就是头节点last = node;return;}// 如果这个链表不为空node.next = head;head.pre = node;head = node;}//尾插法public void addLast(int data){ListNode node = new ListNode(data);if (head == null){head = node;last = node;return; // 一定要记得结果,不然就会执行下面的代码}
// ListNode cur = head;// 这个循环是让cur走到最后一个节点
// while (cur.next!=null){
// cur = cur.next;
// }
// cur.next = node;
// node.pre = cur;last.next = node;node.pre = last;last = node;}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data){ListNode node = new ListNode(data);if (index < 0 || index > size() ){System.out.println("您提供的下标不合法!");return;}if(head == null){if (index==0){head = node;}else {System.out.println("您提供的下标不合法!");}}else { // 就是head不为空的情况// 头插法if (index == 0){addFirst(data);return;}// 尾插法if (index == size()){addLast(data);return;}
// ListNode curNext = null;ListNode cur = head;for (int i = 0; i < index; i++) {cur = cur.next; // cur一直前进到插入位置的前一个}node.next = cur;node.pre = cur.pre;cur.pre.next = node;cur.pre = node;}}//查找是否包含关键字key是否在单链表当中public boolean contains(int key){// 要考虑空链表得情况if (head == null){return false;}// 当非空链表的时候ListNode cur = head;while (cur.next != null){if (cur.val == key){return true;}cur = cur.next;}return false;}//删除第一次出现关键字为key的节点public void remove(int key) {ListNode cur = head;while (cur != null){if (cur.val == key){// 删除头节点if (cur == head){head = head.next;if (head != null){// 考虑只有一个结点的情况head.pre = null;}else {last = null;}}else {// 删除中间节点和末尾节点if (cur.next != null){// 删除中间节点cur.pre.next = cur.next;cur.next.pre = cur.pre;}else {//删除尾巴节点cur.pre.next = cur.next;last = last.pre;}}return;}else {cur = cur.next;}}}//删除所有值为key的节点public void removeAllKey(int key) {ListNode cur = head;while (cur != null){if (cur.val == key) {// 删除头节点if (cur == head) {head = head.next;if (head != null) {// 考虑只有一个结点的情况head.pre = null;} else {last = null;}} else {// 删除中间节点和末尾节点if (cur.next != null) {// 删除中间节点cur.pre.next = cur.next;cur.next.pre = cur.pre;} else {//删除尾巴节点cur.pre.next = cur.next;last = last.pre;}}}cur = cur.next;}}//得到单链表的长度public int size(){int usedSize = 0;ListNode cur = head;while (cur!=null){usedSize++;cur = cur.next;}return usedSize;}// 打印列表里面所有的值public void display(){// 第一步还是要判断一下链表是否为空if (head == null){return;}ListNode cur = head;while (cur != null){System.out.print(cur.val + " ");cur = cur.next; // 要让节点往后走}System.out.println(); // 打印一个空格使其更美观}// 清楚列表里面所有的值public void clear(){ListNode cur = head;while (cur != null){ListNode curNext = cur.next;cur.pre = null;cur.next = null;cur = curNext;}head = null; // 手动置空last = null;}
}
测试代码:
package double_LinkedList;public class Test {public static void main(String[] args) {My_double_LinkedList myDoubleLinkedList = new My_double_LinkedList();/*** 下面是一些方法的测试*/// 1.头插法 + 打印链表里面的所有元素myDoubleLinkedList.addFirst(56);myDoubleLinkedList.addFirst(45);myDoubleLinkedList.addFirst(34);myDoubleLinkedList.addFirst(23);myDoubleLinkedList.addFirst(12);myDoubleLinkedList.display();// 2.尾插法 + 打印链表里面的所有元素myDoubleLinkedList.addLast(99);myDoubleLinkedList.addLast(1314);myDoubleLinkedList.display();// 3.链表的长度int lenth = myDoubleLinkedList.size();System.out.println("目前链表得长度是:" + lenth);System.out.println("==========================");// 4.任意位置插入myDoubleLinkedList.addIndex(0, 11);myDoubleLinkedList.addIndex(6, 888);myDoubleLinkedList.addIndex(3, 666);myDoubleLinkedList.display();myDoubleLinkedList.addIndex(13, 7777);System.out.println("===========================");// 5.找是否包含关键字key是否在单链表当中boolean result1 = myDoubleLinkedList.contains(888);System.out.println(result1);boolean result2 = myDoubleLinkedList.contains(5555);System.out.println(result2);System.out.println("===========================");// 6.删除第一次出现关键字为key的节点myDoubleLinkedList.display();myDoubleLinkedList.remove(1314); // 删除最后一个myDoubleLinkedList.display();myDoubleLinkedList.remove(11); // 删除第一个myDoubleLinkedList.display();myDoubleLinkedList.remove(666); // 删除中间数值myDoubleLinkedList.display();System.out.println("===========================");// 7. 删除所有值为key的节点myDoubleLinkedList.addFirst(1111);myDoubleLinkedList.addFirst(1111);myDoubleLinkedList.addFirst(1111);myDoubleLinkedList.addIndex(4, 1111);myDoubleLinkedList.addLast(1111);myDoubleLinkedList.addLast(1111);myDoubleLinkedList.display();myDoubleLinkedList.removeAllKey(1111);myDoubleLinkedList.display();System.out.println("==========================");}
}
LinkedList的使用
什么是LinkedList
LinkedList的底层是双向链表结构(链表后面介绍),由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
【说明】
1. LinkedList实现了List接口
2. LinkedList的底层使用了双向链表
3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
5. LinkedList比较适合任意位置插入的场景
LinkedList的使用
举个例子:
List<Integer> list = new LinkedList<>();
其他常用方法:
ArrayList和LinkedList的区别
一般从存储和操作两方面进行比较
补充:那顺序表和链表的区别是什么?
相关文章:
LinkedList与链表
ArrayList的缺陷 在上一篇博客中,小编已经较为详细得给大家介绍了ArrayList这个结构了。但是ArrayList存在一些缺陷:由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移&am…...
CCF 编程能力认证 C++ 四级宝典
CCF编程能力等级认证(以下简称GESP)2025年四次认证时间分别为:3月22日、6月28日、9月27日、12月20日,认证方式为线下机考,认证语言包括:C、Python和Scratch三种语言,其中Scratch认证为一到四级&…...
信创系统极速文件查找:locate 命令详解
原文链接:信创系统极速文件查找:locate 命令详解 Hello,大家好啊!今天给大家带来一篇信创终端操作系统上 locate 命令详解的文章。在 Linux 及信创终端操作系统(如 统信 UOS、麒麟 KOS)中,查找…...
数据集获取
sklearn数据集 sklearn有四部分数据。其中sklearn的数据集有两部分真实的数据,一部分嵌入到了sklearn库中,即安装好sklearn后就自带了一部分数据,这些数据的规模比较小称为small toy datasets ,还有一部分数据是需要在网上下载的,sklearn提供了下载的api接口,这些数据规…...
三格电子PLC数据采集网关-工业互联的智能枢纽
在工业自动化领域,设备间的数据互通与协议兼容是核心挑战之一。三格电子推出的PLC据采集网关SG-PLC-Private,凭借其多协议兼容、高稳定性和灵活配置能力,成为工业物联网(IIoT)中实现设备互联的关键设备。本文将从产品功…...
【sgFloatDialog】自定义组件:浮动弹窗,支持修改尺寸、拖拽位置、最大化、还原、最小化、复位
sgFloatDialog <template><div :class"$options.name" v-if"visible" :size"size" :style"style"><!-- 托盘头部 --><div class"header" ref"header" dblclick.stop.prevent"dblclic…...
conda 常用命令
常用 Conda 命令整理环境管理 conda create --name 环境名 :创建新环境 conda activate 环境名 :激活环境 conda deactivate:退出环境 conda env list:列出所有环境 conda remove --name 环境名 --all :删除环…...
神聖的綫性代數速成例題10. N維矢量綫性運算、矢量由矢量組綫性表示、N個N維矢量相關性質
N 維矢量綫性運算: 設,是維矢量,是數。加法:。數乘:。 矢量由矢量組綫性表示: 設是n維矢量,若存在一組數,使得,則稱矢量可由矢量組綫性表示。 N 個 N 維矢量相關性質&…...
力扣977. 有序数组的平方(双指针技巧)
Problem: 977. 有序数组的平方 文章目录 题目描述思路Code 题目描述 思路 由于数组是非递减且包含正、负数,则假如我们将数组中的每一个元素取平方并且将其从原始的某一个位置分开成两个数组来看待(一个数组从前往后看,一个数组从后往前看&am…...
单片机flash存储也做磨损均衡
最近在做一个项目,需要保存设置数据,掉电不丢失。那么首先想到的是加个24c02,是一个eeprom,但是客户板太小,没有办法进行扩展。后面就找了一个带ee的OTP单片机,发现擦写次数有限,只有1000次&…...
第7章 类与面向对象
6-1 二维平面上的点操作(Python3) 题目描述 设计一个表示二维平面上点的类 Point。该类应该包含以下功能: 两个私有属性 _x 和 _y,分别表示点的横坐标和纵坐标。 一个构造函数 __init__,用于初始化点的坐标。 一个…...
【算法】力扣 713题:乘积小于 K 的子数组之深入思考
文章目录 前言题目:乘积小于 K 的子数组参考思路方法一:滑动窗口方法二:二分查找 参考题解方法一:滑动窗口解法方法二:二分查找解法 深入思考浮点精度?right - left 1?二分法?哈希优…...
Milvus vs. ElasticSearch:向量库检索性能测试
目录 1. 构建检索库2. 测试条件3. 测试结果4. 性能分析5. 结论 1. 构建检索库 构建通用场景库总计约2万张。构建车辆数据库总计约12万张。构建公共数据库,包括Flickr30k、COCO、nlvr2、vqa等数据集约43万张。 2. 测试条件 环境说明:分别单机部署Milvu…...
高级数据结构应用:并查集、跳表、布隆过滤器与缓存结构
高级数据结构应用:并查集、跳表、布隆过滤器与缓存结构 在解决复杂问题时,选择合适的数据结构往往是成功的关键。本文将深入探讨四种强大而实用的高级数据结构:并查集、跳表、布隆过滤器和高效缓存结构(LRU和LFU),包括它们的原理、实现、复杂度分析和实际应用场景。 1.…...
CVPR2025 | 蚂蚁浙大提出MP-GUI算法:全方位增强MLLM的GUI理解能力
近日,计算机视觉和模式识别领域国际顶会CVPR 2025公布了论文录用结果,蚂蚁集团与浙江大学EAGLE实验室合作的论文 “MP-GUI: Modality Perception with MLLMs for GUI Understanding” 被成功录用。 IEEE国际计算机视觉与模式识别会议(CVPR&a…...
过河卒cpp动态规划
题目如下 思路 利用二维数组存储棋盘的各个点的位置,首先初始化所有位置为0,然后记马的位置为1,将m,n同时加2,避免马的位置溢出,然后对二维数组进行递推算出dp[n][m] 代码及解析如下 谢谢观看!…...
春天咋会像冬天一样
2025年3月20日,阴,天寒 遇见的事:21~24号去曲靖招生,打电话给我说换一下,换了后又没有车了,这么坑。 感受到的情绪:你知道么,换的前提是有车。开车不给报销,…...
DooTask在Linux的离线部署教程
DooTask在Linux的离线部署教程 下载安装包 从网盘中将安装包下载到本地,下载地址 通过网盘分享的文件:DooTask项目管理工具 链接: https://pan.baidu.com/s/1hGmLXonT4c8hLiDP1QBr8w?pwdgdp6 提取码: gdp6 通过网盘分享的文件:DooTask项目…...
分享下web3j 常见用法
转账 fun sendEthTransaction(privateKey: String,toAddress: String,amount: BigDecimal) {//chainIdval chainId:Long 1//url 可以从https://chainlist.org/里面获取可用节点//eth转账,bnb同理,但需发送到bnb对应节点val url "https://xxx"…...
跨域问题确认及处理
背景如下: 近期在做的项目中,有个奇怪的需求,需要在JSP项目中嵌套一个VUE项目,原因是:JSP项目是在运且不大方便重构的一个项目,新需求又想为了未来着想做一套单独的项目,无奈只能嵌套。 当项目开…...
PyCharm如何添加已有的conda环境
1、点击文件中的设置 2、在右侧选中项目下的Python解释器 3、在右侧解释器一栏找到添加解释器选项 4、选择本地解释器 5、填写信息 环境:选择现有 类型:conda conda路径:...\Anaconda\Scripts\conda.exe 环境(python路径&…...
揭开最大子段和问题的神秘面纱:从暴力法到极致优化的算法之旅
最大子段和问题:从暴力法到优化的算法解析 题目链接 题目描述 给出一个长度为 nn 的序列 aa,选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数,表示序列的长度 n。第二行有 n 个整数,第 i 个整数表示序列的…...
MySQL原理:逻辑架构
目的:了解 SQL执行流程 以及 MySQL 内部架构,每个零件具体负责做什么 理解整体架构分别有什么模块每个模块具体做什么 目录 1 服务器处理客户端请求 1.1 MySQL 服务器端逻辑架构说明 2 Connectors 3 第一层:连接层 3.1 数据库连接池(Conn…...
提升模型性能:数据增强与调优实战
一、为什么需要数据增强? 数据增强通过对训练图像进行随机变换,能够有效: 增加数据多样性,防止过拟合提升模型对不同视角、光照条件的鲁棒性在数据量不足时显著提升模型性能 二、MNIST手写数字识别实战 1. 加载数据…...
Emacs 折腾日记(十八)——改变Emacs的样貌
截止到上一篇文章为止,之前教程 的内容都看完了,虽然它的后记部分提供了一些后续进阶的内容需要我们自己读手册。但是我不太想继续在elisp上死磕了。看着自己学了那么久的elisp,但是自己的emacs仍然没有半点改变,这个时候各位读者…...
VNA操作使用学习-14 再测晶振特性
再测一下4Mhz晶振,看看特性曲线,熟悉一下vna使用。 s11模式,找遍了各种format都无法显示,只有这一种(s11,Resistance)稍微显示出一个谐振,但是只有一个点。 s21模式 这是201p&#…...
CentOS7 离线下载安装 GitLab CE
依赖下载 https://vault.centos.org/7.9.2009/os/x86_64/Packages/policycoreutils-python-2.5-34.el7.x86_64.rpm 依赖安装 rpm -ivh policycoreutils-python-2.5-34.el7.x86_64.rpm 查看是否安装依赖 rpm -qa | grep policycoreutils-pythongitlab下载 https://packag…...
LeetCode 热题 100_跳跃游戏 II(79_45_中等_C++)(贪心算法)
LeetCode 热题 100_跳跃游戏 II(79_45) 题目描述:输入输出样例:题解:解题思路:思路一(贪心选择): 代码实现代码实现(思路一(贪心算法)…...
《Linux系统编程篇》Linux Socket 网络编程01 API介绍(Linux 进程间通信(IPC))——基础篇
文章目录 引言1. **创建Socket**2. **绑定Socket**3. **监听Socket**4. **接受客户端连接**5. **连接服务器**6. **发送数据**7. **接收数据**8. **发送数据(UDP)**9. **接收数据(UDP)**10. **关闭Socket**11. **设置/获取Socket选…...
系统思考—啤酒游戏经营决策沙盘模拟
再次感谢文华学院的邀请,为经纬集团管理层带来 《啤酒游戏经营决策沙盘》! 很多朋友问:“最近是不是啤酒游戏上的少了?” 其实,真正的关键不是游戏本身,而是——如何让大家真正看见复杂系统中的隐性结构。 …...
利用设计模式构建事件处理系统
在现代软件开发中,设计模式提供了一种可重用的解决方案来解决常见的设计问题。在这篇博客中,我们将探讨如何利用模板方法模式、责任链模式、建造者模式以及线程安全设计来构建一个灵活且可扩展的事件处理系统。 设计模式及其应用 1. 模板方法模式 应用…...
ThreadLocal 的详细使用指南
一、ThreadLocal 核心原理 ThreadLocal 是 Java 提供的线程绑定机制,为每个线程维护变量的独立副本。其内部通过 ThreadLocalMap 实现,每个线程的 Thread 对象都有一个独立的 ThreadLocalMap,存储以 ThreadLocal 对象为键、线程局部变量为值…...
全员DeepSeek时代,前端能做些什么?
全员DeepSeek时代,前端能做些什么? 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc #mermaid-svg-VNyL95jkz9jEXgUq {font-family:&…...
阿里云 AI 搜索产品荣获 Elastic Innovation Award 2024
阿里云AI搜索产品荣获Elastic Innovation Award 2024,该奖项于近日在新加坡ElasticON 2025的Elastic合作伙伴峰会上颁发,旨在表彰基于Elastic平台开发企业级生成式人工智能(GenAI)应用的顶尖合作伙伴,这些应用有效帮助…...
html5制作2048游戏开发心得与技术分享
2048游戏开发心得与技术分享 这里写目录标题 2048游戏开发心得与技术分享项目概述技术架构1. 核心技术栈2. 项目结构 核心功能实现1. 数据结构设计2. 移动逻辑实现3. 触摸支持 性能优化1. DOM操作优化2. 事件处理优化 开发心得1. 代码组织2. 调试技巧3. 用户体验优化 项目亮点技…...
AI日报 - 2025年3月21日
🌟 今日概览(60秒速览) ▎🤖 AGI突破 | OpenAI成立安全委员会,加速AGI治理框架构建 ▎💼 商业动向 | 微软发布医疗大模型DAX Copilot 3.0,覆盖全球临床场景 ▎📜 政策追踪 | 中国发布…...
MyBatis-Plus:告别手写 SQL 的高效之道
目录 1. MyBatis-plus 简介 2. MyBatis-Plus 快速上手 2.1 项目准备 2.2 导入 MyBatis-Plus 依赖 2.3 配置数据库连接 2.4 配置 MyBatis-Plus 日志打印 3. 使用 MyBatis-Plus 3.1 创建 model 类 3.2 创建 mapper 接口 3.3 MyBatis-Plus 映射机制 3.3.1 TableName &a…...
【AI News | 20250320】每日AI进展
AI Repos 1、servers 该仓库提供详细入门指南,用户可通过简单步骤连接Claude客户端,快速使用所有服务器功能。此项目由Anthropic管理,展示MCP的多样性与扩展性,助力开发者为大语言模型提供安全、可控的工具与数据访问。 2、awe…...
让“树和二叉树”埋在记忆土壤中--性质和概念
Nice to meet your! 目录 树的介绍: 树的创建: 二叉树的概念和结构: 二叉树的存储结构: 树的介绍: 概念和结构: 不知你们是否在现实中看见过分为两个叉的枯树,大概长这样: 那…...
210、【图论】课程表(Python)
题目 思路 这道题本质上是一个拓扑排序。每次先统计每个点的入度个数、然后再统计点与点之间的邻接关系,找到入度为0的点作为起始遍历点。之后每遍历到这个点之后,就把这个点后续的邻接关系边的点入度减去一。当某个点入度为0时,继续被加入其…...
【Linux篇】进程控制
📌 个人主页: 孙同学_ 🔧 文章专栏:Liunx 💡 关注我,分享经验,助你少走弯路! 1. 进程创建 1.1 fork函数 在linux中fork函数是非常重要的函数,它从已存在进程中创建一个…...
freeswitch(在呼叫失败的情况下如何播放语⾳提⽰)
亲测版本centos 7.9系统–》 freeswitch1.10.9 本人freeswitch安装路径(根据自己的路径进入) /usr/local/freeswitch/etc/freeswitch⼀般我们在打电话时会听到『您拨的电话正在通话中,请稍后再 拨.』,或『电话⽆应答』之类的提⽰,我们在 FreeSWITCH ⾥也可以这样做。 …...
软考系统架构设计师之计算机组成与体系结构笔记
一、计算机硬件组成 1. 冯诺依曼结构与哈佛结构 冯诺依曼结构:以存储器为中心,指令和数据统一存储,通过总线连接运算器、控制器、输入输出设备。其核心思想是“存储程序控制”,但存在存储器访问瓶颈问题。哈佛结构:指…...
gonet开源游戏服务器环境配置
1.mysql搭建 搜索mysql-server apt安装包名 sudo apt search mysql-server 安装mysql-server sudo apt-get install mysql-server 安装完成后会,启动mysql服务及创建系统服务 查看服务状态 systemctl status mysql.service 使用超级权限登陆mysql sudo mysql 授…...
软件工程之软件验证计划Software Verification Plan
个人主页:云纳星辰怀自在 座右铭:“所谓坚持,就是觉得还有希望!” 本文为基于ISO26262软件验证计划模板,仅供参考。 软件验证计划,包括: 1. 软件需求验证计划 2. 软件架构设计验证计划 3. 软件单…...
大模型详细配置
Transformer结构 目前主力大模型都是基于Transformer的,以下是Transformer的具体架构 它由编码器(Encoder)以及解码器(Decoder)组成,前者主要负责对输入数据进行理解,将每个输入 词元都编码成一个上下文语义相关的表示向量;后者…...
Web爬虫利器FireCrawl:全方位助力AI训练与高效数据抓取
Web爬虫利器FireCrawl:全方位助力AI训练与高效数据抓取 一、FireCrawl 项目简介二、主要功能三、FireCrawl应用场景1. 大语言模型训练2. 检索增强生成(RAG):3. 数据驱动的开发项目4. SEO 与内容优化5. 在线服务与工具集成 四、安装…...
产业观察:ASML2025.3.21
一.发展历程 1.1 创业背景 在半导体行业的快速发展背景下,ASML的创业故事拉开了帷幕。1983年, 飞利浦S&I技术总监Georg de Kruyff 与 ASM创始人Arthur del Prado 重启合作讨论,为ASML的创立奠定了基础。双方迅速达成协议,计…...
go语言学习教程推荐,零基础到做项目
一、基础入门阶段 官方教程(免费) • A Tour of Go:交互式入门教程,边学边练 • Go by Example:通过300代码片段学习语法 入门书籍 • 📘《Go语言圣经》中文版(免费在线阅读)&#…...
设计模式 二、创建型设计模式
GoF是 “Gang of Four”(四人帮)的简称,它们是指4位著名的计算机科学家:Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides。他们合作编写了一本非常著名的关于设计模式的书籍《Design Patterns: Elements of Reusable…...