数据结构之链表的经典笔试题

 找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏:数据结构(Java版)

目录

203. 移除链表元素

206. 反转链表

876. 链表的中间节点

面试题 02.02. 返回倒数第k个节点

快慢指针的原理分析 

21. 合并两个有序链表

牛客网——链表的回文

牛客网——链表分割

160. 相交链表

 141. 环形链表

142. 环形链表 II


单链表的刷题,点我

下面的这些面试题有一部分在上面这篇博文中,有兴趣可以看一看。

下列题目中出现的这个,是出题者想告诉我们这个链表的节点是由什么组成的。 

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
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

思路:就是遍历链表,找到所有值为val的节点,并删除即可。 

class Solution {public ListNode removeElements(ListNode head, int val) {// 删除链表中所有值为节点// 首先判断链表是否为空if (head == null ) {// 链表为空,肯定head为空return head;}ListNode cur = head;while (cur.next != null) {// 找到值为val的前一个节点if (cur.next.val == val) {cur.next = cur.next.next;}else {// 没找到就继续往后找cur = cur.next;}}// 判断头节点是否为valif (head.val == val) {head = head.next;}return head;}
}

206. 反转链表

给你单链表的头节点 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

思路:遍历原链表,将其中的所有节点全部头插到原链表中。

class Solution {public ListNode reverseList(ListNode head) {// 当链表为空,或者只有一个节点时,就直接返回原链表if (head == null || head.next == null) {return head;}// 开始头插ListNode cur = head.next;// 这个要变为null,否则就会成环。// 因为这个节点是最后一个节点,而最后一个节点的next值不为null,就会造成错误head.next = null; while (cur != null) {ListNode curNext = cur.next;cur.next = head; head = cur;cur = curNext;}return head;}
}

876. 链表的中间节点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:head = [1,2,3,4,5]
输出:[3,4,5]
解释:链表只有一个中间结点,值为 3 。

示例 2:

输入:head = [1,2,3,4,5,6]
输出:[4,5,6]
解释:该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点。

提示:

  • 链表的结点数范围是 [1, 100]
  • 1 <= Node.val <= 100

思路一:通过遍历链表得出链表的长度,然后让cur从头节点开始走 长度的一半 的步数,那么这个节点的位置就是中间节点。

思路二:通过快慢指针的方式来解题。快指针fast,一次走两步,慢指针slow,一次走一步。当快指针走到链表的尾节点处时,慢指针就是在当前链表的中间节点。

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;}
}

面试题 02.02. 返回倒数第k个节点

 实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

注意:本题相对原题稍作改动

示例:

输入: 1->2->3->4->5 和 k = 2
输出: 4

说明:

给定的 k 保证是有效的。

思路一:遍历得出链表的长度,然后用长度减去k,得出的结果就是cur要走的步数。

思路二:通过快慢指针的方式来解题。快指针先走k-1步,然后快指针和慢指针一起走,直至快指针到达尾节点,这时慢指针的位置就是倒数第k个节点的位置。

class Solution {public int kthToLast(ListNode head, int k) {ListNode fast = head;ListNode slow = head;while ((k-1) > 0) {fast = fast.next;k--;}while (fast.next != null) {fast = fast.next;slow = slow.next;}return slow.val;}
}

快慢指针的原理分析 

通过这两题,我们来分析快慢指针的原理。

链表的中间节点 —— 假设有两个人在同一时间赛跑,fast是slow的速度的二倍,当fast到达终点时,这个slow就会在这个总路程的一半处。因此就可以得出中间节点的位置。

返回倒数第k个节点 —— fast先走k-1步,那么fast与slow就相差k-1步,当两者一起走,并且fast走到了终点时,这时fast与slow还是相差k-1步,那么这个slow就是倒数第k个节点(因为fast的位置是倒数第一个节点)。

21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

思路:创建一个新的带头链表。通过遍历两个链表,比较两者的大小,将 小的val值 对应的节点尾插到这个带头链表中,直至有一方节点结束,再把另一方的节点直接尾插到新链表即可。

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {// 当list1为空或者list1与list2都为空时,直接返回list2if (list1 == null) {return list2;}if (list2 == null) {return list1;}// 创建一个新的头节点ListNode head = new ListNode(-1);ListNode cur = head;ListNode cur1 = list1;ListNode cur2 = list2;while (cur1 != null && cur2 != null) {if (cur1.val > cur2.val) {// 尾插cur2cur.next = cur2;cur2 = cur2.next;}else {// 尾插cur1cur.next = cur1;cur1 = cur1.next;}// 因为这一行代码无论走哪里,都会进行,因此放到外边来cur = cur.next;}// 还有一方还剩节点if (cur1 != null) {// 尾插cur1就行了,因为原来就是链表,因此不用循环cur.next = cur1;}if (cur2 != null) {// 尾插cur2就行了,因为原来就是链表,因此不用循环cur.next = cur2;}return head.next;}
}

牛客网——链表的回文

描述

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

测试样例:

1->2->2->1
返回:true

思路:虽然描述很简洁,但是难度却是比较大的一题。按照我们以往写回文的思路,就是定义一个left 和 right 指针指向两头,遍历比较。遇到不相等的就直接返回false,遍历完就返回true。但很可惜这题是单链表不能够反向遍历。既然不能直接反向遍历,那么我们就把这个后面的链表反转一下,变成可以反向遍历的情况。那问题又来了:从哪里开始反转呢?我们想一下,普通回文遍历的结束条件是left < right ,也就是两者相遇或者说是到了中间位置就可以停止了。那么我们这里的反转也就可以从中间位置开始。反转完,之后就可比较了。因此,最终要做的事情就是:

1. 找到链表的中间节点;

2. 从中间位置开始反转;

3. 从两头开始遍历比较。

下面是反转的具体分析过程:

public class PalindromeList {public boolean chkPalindrome(ListNode A) {// 当链表为空或者只有一个节点时,必回文if (A == null || A.next == null) {return true;}// 找到中间节点ListNode fast = A;ListNode slow = A;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;}ListNode cur = slow.next;// 从中间节点往后反转// 当slow走到尾节点时,就可以不必再继续了while (cur != null) {ListNode curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;}// 开始遍历回文// 这里不要用fast,因为fast可能不在尾节点while (A != slow) {if (A.val != slow.val) {return false;}// 当链表长度为偶数时,会出现一种情况(后面细说)if (A.next == slow) {return true;}A = A.next;slow = slow.next; }return true;}
}

反转也不能写成下面这样:

    while (slow.next != null) {ListNode cur = slow.next;ListNode curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;}

上面的代码会陷入死循环。因为在最后修改了 slow 的位置,变成了 cur,所以 slow.next 是指向的位置是原来的 slow 。因此最终就陷入了死循环。如下图:

最后,我们会发现其实改来改去最终都在兜圈子。 

综上本题来看,难度确实是挺大的,要注意的细节也是挺多的,无愧于 字节跳动 的秋招笔试题。 

牛客网——链表分割

描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

思路:既然要分割链表,那我们直接按照原来的链表顺序遍历,把小于 x 的节点放到小链表中,其余节点放到大链表中。 

我们就会不假思索的写出下面的代码:

public class Partition {public ListNode partition(ListNode pHead, int x) {// 这题比较虾仁猪心:思路简单,但细节很多// 如果链表为空或者链表只有一个节点,就直接返回该节点if (pHead == null || pHead.next == null) {return pHead;}// 为了更为方便,我们定义头节点和尾节点ListNode beforeStart = null;ListNode beforeEnd = null;ListNode afterStart = null;ListNode afterEnd = null;// 遍历链表,小于放一边,大于放一边,然后小的串大的while (pHead != null) {if (pHead.val < x) {// 尾插到小链表中if (beforeStart == null) {beforeStart = pHead;beforeEnd = pHead;} else {beforeEnd.next = pHead;beforeEnd = beforeEnd.next;}} else {// 尾插到大链表中if (afterStart == null) {afterStart = pHead;afterEnd = pHead;} else {afterEnd.next = pHead;afterEnd = afterEnd.next;}}pHead = pHead.next;}beforeEnd.next = afterStart;return beforeStart;}
}

但上面的代码在测试的时候,会抛出空指针异常。其实就是当小链表为空(链表中所有的值均大于 x)时,这个 beforeStart 为空,那么去访问其 next 值时,就会发生空指针异常。因此,当小链表为空时,直接返回大链表,当大链表为空时,直接返回小链表即可。但很遗憾,又出现了死循环的问题:如下图所示:

因此,我们还得把 afterEnd 的 next 置为null。 通过一系列的纠正,最终的代码如下:

public class Partition {public ListNode partition(ListNode pHead, int x) {// 这题比较虾仁猪心:思路简单,但细节很多// 如果链表为空或者链表只有一个节点,就直接返回该节点if (pHead == null || pHead.next == null) {return pHead;}// 为了更为方便,我们定义头节点和尾节点ListNode beforeStart = null;ListNode beforeEnd = null;ListNode afterStart = null;ListNode afterEnd = null;// 遍历链表,小于放一边,大于放一边,然后小的串大的while (pHead != null) {if (pHead.val < x) {// 尾插到小链表中if (beforeStart == null) {beforeStart = pHead;beforeEnd = pHead;} else {beforeEnd.next = pHead;beforeEnd = beforeEnd.next;}} else {// 尾插到大链表中if (afterStart == null) {afterStart = pHead;afterEnd = pHead;} else {afterEnd.next = pHead;afterEnd = afterEnd.next;}}pHead = pHead.next;}// 把小链表和大链表串起来if (beforeEnd == null) {// 如果小链表为空,那么就直接返回大链表// 那么大链表就是按照原来链表的顺序,即无需将最后节点的next置为nullreturn afterStart;}if (afterStart == null) {return beforeStart;}beforeEnd.next = afterStart;afterEnd.next = null;return beforeStart;}
}

这题虽然思路简单,但要注意的细节很多,稍一疏忽,就会犯错。简直就是:虾仁猪心 。

160. 相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
  • listA - 第一个链表
  • listB - 第二个链表
  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数

评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

 

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

示例 2:

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

提示:

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 1 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA] == listB[skipB]

思路: 两个链表相交,有一个特点就是:相交之后的链表长度一定是相同的。假设前面不相交的长度是想等的,定义一个 cur1 指向一个链表,定义一个 cur2 指向另一个链表,去遍历两个链表,当两者不相等时,就一直遍历,直至相等为止。但遗憾的是两者长度会出现不一样的情况,这里依然是使用快慢指针的方法。当长度不相等时,就让 长度长的链表 先走 两者的差值步数,然后再一起走,那么最终的结果一定是两者一起走到相等或者两者走到都为 null。最终的步骤:

1、先算出两者的长度,求其长度差。

2、再让长度长的链表走长度差步

3、接着两者一起走,判断是否相等

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 先算出各自长度,让长的链表走两者长度的差值步,再一起走,如果相遇则其相交。ListNode cur1 = headA;ListNode cur2 = headB;int len1 = 0;int len2 = 0;while (cur1 != null) {len1++;cur1 = cur1.next;}while (cur2 != null) {len2++;cur2 = cur2.next;}if (len1 > len2) {// 让headA走差值步cur1 = headA;cur2 = headB;int len = len1 - len2;while (len-- > 0) {cur1 = cur1.next;}// 开始比较while (cur1 != cur2) {cur1 = cur1.next;cur2 = cur2.next;}// 走到这里,有两种情况:1、cur1与cur2 都为空了,跳出了循环// 2、两者确实是相遇了。 我们只需判断一下即可if (cur1 == null) {return null;}// 其实这里不判断,也可以运行通过,因为题目要求不相遇就返回null,// 而比较到null时,cur1也是null,所以返回cur1也是对的(碰巧)。return cur1;}else {// 让headB走差值步cur1 = headA;cur2 = headB;int len = len2 - len1;while (len-- > 0) {cur2 = cur2.next;}// 开始比较while (cur1 != cur2) {cur1 = cur1.next;cur2 = cur2.next;}// 走到这里,有两种情况:1、cur1与cur2 都为空了,跳出了循环// 2、两者确实是相遇了。 我们只需判断一下即可if (cur1 == null) {return null;}// 其实这里不判断,也可以运行通过,因为题目要求不相遇就返回null,// 而比较到null时,cur1也是null,所以返回cur1也是对的(碰巧)。return cur1;}}
}

上面的代码在后面一起走的部分中大部分代码是一致的,因此就可以简化为下面这样:

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 先算出各自长度,让长的链表走两者长度的差值步,再一起走,如果相遇则其相交。ListNode cur1 = headA;ListNode cur2 = headB;int len1 = 0;int len2 = 0;while (cur1 != null) {len1++;cur1 = cur1.next;}while (cur2 != null) {len2++;cur2 = cur2.next;}// 假设headA为长链表int len = len1-len2;cur1 = headA;cur2 = headB;if (len < 0) {// 说明headB是长链表len = - len;cur1 = headB;cur2 = headA;}// 走到这里,长链表一定已经确定了while (len-- > 0) {cur1 = cur1.next;}while (cur1 != cur2) {cur1 = cur1.next;cur2 = cur2.next;}if (cur1 == null) {return null;}return cur1;}
}

 141. 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

  • 链表中节点的数目范围是 [0, 104]
  • -105 <= Node.val <= 105
  • pos 为 -1 或者链表中的一个 有效索引 。

思路:快慢指针。当一个链表没有环,那么肯定是快指针先走到终点,如果一个链表有环,则快指针会先入环,接着慢指针再入环,最终快慢指针会相遇(一定是快指针走两步,慢指针走一步,这样快指针才不会包含慢指针)。如果快指针走三步,就有可能出现慢指针一直在快指针中间的情况。

public class Solution {public boolean hasCycle(ListNode head) {// 如果链表为空或者链表的第一个节点的next为空,则说明没有成环if (head == null || head.next == null) {return false;}ListNode fast = head;ListNode slow = head;// 快指针如果遇到结尾的情况就可以停止了while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;// 一定要走完才能判断if (fast == slow) {return true;}}return false;}
}

其实,我们仔细观察会发现:在快指针还没开始走的时候,while循环的判断条件和前面的if判断条件是一样的,都是判断链表是否为空或者是链表的第一个节点的 next 值是是否为空。

public class Solution {public boolean hasCycle(ListNode head) {ListNode fast = head;ListNode slow = head;// 快指针如果遇到结尾的情况就可以停止了while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;// 一定要走完才能判断if (fast == slow) {return true;}}return false;}
}

142. 环形链表 II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

提示:

  • 链表中节点的数目范围在范围 [0, 104] 内
  • -105 <= Node.val <= 105
  • pos 的值为 -1 或者链表中的一个有效索引

思路: 这个题目的意思就是让我们找到链表的第一个成环的节点。如下图所示:

上面那种情况只是我们认为的理想情况:慢指针入环时,快指针刚好只走完一圈,但是实际走完几圈我们是不确定的,因此可以设 n 为快指针走的圈数,带入求解的结果就是:x = n*m - y = (n-1)*m + (m-y),最终结果还是我们前面的结论。因为 (n-1)只是圈数,最终还是会停在这个相遇点。

这里最重要的是抓住:快指针走的路程是慢指针的两倍。 

1、找到相遇点

2、慢指针从头走,快指针从相遇点走,都以相同的速度。

public class Solution {public ListNode detectCycle(ListNode head) {// 找到相遇点ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;// 相遇就停下来if (slow == fast) {break;}}// 链表里没有环的情况有几种:if (fast != slow || head == null || head.next == null) {// 说明没有环return null;}// slow从链表头开始走,fast从相遇点开始走slow = head;while (slow != fast) {fast = fast.next;slow =slow.next;}return slow;}
}

因为这里在相遇之后,还要执行代码,就必须要判断链表是否为空和只有一个节点无环的情况。 

好啦!本期 数据结构之链表的经典笔试题 的学习之旅就到此结束啦!我们下一期再一起学习吧!

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

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

相关文章

【AI】文心一言的使用分享

在数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;技术的飞速发展正在改变我们的生活。文心一言&#xff0c;作为这一浪潮中的佼佼者&#xff0c;以其卓越的自然语言处理能力和广泛的应用场景&#xff0c;给我带来了前所未有的使用体验。在这篇分享中&#xff0c;我…

Spring Cloud Bus 消息总线基础入门与实践总结

【1】基础介绍 其主要是实现分布式自动刷新配置功能&#xff0c;Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架&#xff0c;它整合了Java的事件处理机制和消息中间件的功能…

Wall国内开源程序照片墙,支持VR全景及安装教程

下载 GitHub官网&#xff1a;https://github.com/zhang-tong-yao/wall 软件下载&#xff1a;https://github.com/zhang-tong-yao/wall/releases&#xff0c;推荐下载最新的版本。 演示效果 目前支持PC端和移动端自适应。 演示地址&#xff1a;https://demo-wall.ityao.cn …

农产品商城系统农资电商商城系统java项目jsp web项目

农产品商城系统农资电商商城系统java项目jsp web项目 会员用户可以实现&#xff1a;注册登录、商品信息浏览、加入购物车、加入收藏、下单支付、查看公告、查看以及留言、个人信息管理 后台管理的实现&#xff1a;类别管理模块、商品管理模块、会员管理模块、订单管理、退货管…

你项目用到了 Dubbo,讲讲为什么要用以及怎么使用的?

引言&#xff1a;在现代分布式系统中&#xff0c;服务化架构已成为构建高性能、可扩展和可靠系统的关键。 Dubbo 作为一种优秀的服务化框架&#xff0c;提供了丰富的特性和灵活的配置选项&#xff0c;使得它在业界得到了广泛的应用和认可。本文将探讨为什么选择 Dubbo 以及如何…

JavaEE大作业之班级通讯录系统(前端HTML+后端JavaEE实现)PS:也可选网络留言板、图书借阅系统、寝室管理系统

背景&#xff1a; 题目要求&#xff1a; 题目一&#xff1a;班级通讯录【我们选这个】 实现一个B/S结构的电子通讯录&#xff0c;其中的每条记录至少包含学号、姓名、性别、班级、手机号、QQ号、微信号&#xff0c;需要实现如下功能&#xff1a; &#xff08;1&#xff09;…

Objective-C基础语言开发来袭,你准备好了吗?

文/ZaiZai 前言 今天小白电脑技术的公众号迎来了一位Objective-C语言开发大神——ZaiZai。接下来有想要学习写插件&#xff08;iOS/macOS/iPadOS/tvOS&#xff09;的小伙伴可以关注微信公众号&#xff0c;教程将持续更新。 ZaiZai个人介绍……呃……他不让放。 Objective-C…

AI早班车6.13

全球AI新闻速递 1.Yandex 开源模型训练工具“YaFSDP”&#xff0c;提升 GPU 利用率。 2.全天候激光智能除草机器人落地&#xff0c;环境零污染。 3.苹果2024开发者大会-Siri 更智能。 4.CampusAI筹集1000万美元种子资金&#xff0c;创建虚拟校园用于学习AI技能。 5.OpenAI&…

C语言详解(预编译)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

什么是DMZ?路由器上如何使用DMZ?

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 DMZ 📒🚀 DMZ的应用场景💡 路由器设置DMZ🎈 注意事项 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 在网络管理中,DMZ(Demilitarized Zone,隔离区)是一个特殊的网络区域,常用于将公共访问和内部网络隔离开来。DMZ功能允许…

遇到JSON文件就头大?掌握Python这几种方法,让你轻松应对

目录 1、标准库json模块 📄 1.1 json.load()函数介绍 1.2 json.loads()处理字符串 1.3 使用json.dump()写入JSON 1.4 json.dumps()美化输出 1.4 错误处理与编码问题 1.5 高效读取大文件技巧 2、第三方库simplejson加持 🔧 2.1 安装与导入simplejson 2.2 性能优势与…

解决css文本内容为符号不会换行问题

错误样式如上&#xff0c;超出了规定的文本区域。 在css上增加word-wrap: break-word;即可。

电商价格监测对于品牌渠道管控的重要性

当品牌开启经销渠道或涉足电商渠道时&#xff0c;必须着手进行线上线下价格监测。只有监控到电商价格&#xff0c;才能明晰出货后的商品历经多轮市场演绎后的实际价格&#xff0c;进而了解市场需求下的真实低价行为。借助力维网络开发的电商价格监测系统&#xff0c;品牌商能知…

uni-app利用renderjs实现安卓App上jssip+freeswitch+webrtc音视频通话功能

效果图 前置知识 利用renderjs在app端加载for web库 JsSIPFreeSwitchVue实现WebRtc音视频通话 原始模块 <template><viewclass"test-sip":userExtension"userExtension":change:userExtension"JsSIP.handleUserExtenSionChange":tar…

Python邮箱发送如何设置?Python发信方法?

Python邮箱发送邮件需要哪些库&#xff1f;怎么使用Python发信&#xff1f; Python的强大之处在于其丰富的库和模块&#xff0c;使得开发者可以轻松地实现各种功能&#xff0c;包括通过电子邮件发送信息。AokSend将介绍如何在Python中设置和发送电子邮件&#xff0c;以及相关的…

超高频载码体有哪些特点?

载码体由线圈、已编程的芯片&#xff0c;以及电池(在有源读写系统中)组成&#xff0c;具有唯一的电子编码&#xff0c;拥有大容量的存储空间&#xff0c;通常附着于产品载体乃至是产品本身&#xff0c;成为一个随产品移动的移动数据库&#xff0c;可以帮助企业更好的物料、成品…

AH8652:220V转5V非隔离电源芯片

### AH8652&#xff1a;220V转5V非隔离电源芯片&#xff0c;高效转换新选择 #### 引言 随着电子设备对电源稳定性和安全性要求的提高&#xff0c;非隔离电源转换芯片因其简单、高效和成本效益而受到市场的欢迎。AH8652是一款专为220V转5V设计的非隔离电源芯片&#xff0c;以其…

Ubuntu安装Protobuf

以前的版本中&#xff0c;有./configure&#xff0c;所以参照下面的博客链接 Ubuntu安装Protobuf&#xff0c;指定版本_ubuntu更新protobuf-CSDN博客 后来的版本中&#xff0c;没有了./configure文件&#xff0c;需要安装bazel,参照下面的官网链接 protobuf/src/README.md a…

基于 Redis 实现分布式缓存

一、单节点 Redis 的问题 1.1 存在的问题 1、数据丢失问题&#xff1a;Redis 是内存存储&#xff0c;服务重启可能会丢失数据。 2、并发能力问题&#xff1a;单节点 Redis 并发能力虽然不错&#xff0c;但也无法满足如 618 这样的高并发场景。 3、故障恢复问题&#xff1a;如果…

实践分享:鸿蒙跨平台开发实例

先来理解什么是跨平台 提到跨平台&#xff0c;要先理解什么是“平台”&#xff0c;这里的平台&#xff0c;就是指应用程序的运行环境&#xff0c;例如操作系统&#xff0c;或者是Web浏览器&#xff0c;具体的像HarmonyOS、Android、iOS、或者浏览器&#xff0c;都可以叫做平台…