[数据结构] 详解链表(超详细)

news2025/1/12 6:42:44

链表可是很重要的知识,是面试时常考的知识点,这次让我们系统的学习一下吧

文章目录

  • 1. 链表的定义
  • 2. 链表的创建
    • 2.1 基础创建
    • 2.2 尾插法创建头节点
    • 2.3 头插法
  • 3. 链表的基础方法
    • 3.1 获取链表长度
    • 3.2 是否包含某个节点
    • 3.3 在任意坐标处插入节点
    • 3.4 删除第一个值为key的节点
    • 3.5 删除所有节点值为key的节点
  • 4. 链表的进阶方法
    • 4.1 反转链表
    • 4.2 找出中间节点
    • 4.3 找出倒数第K个节点
    • 4.4 用数值x分割列表
    • 4.5 判断是否为回文链表
    • 4.6 判断链表是否有环
      • 1. 附加 给链表添加环
    • 4.7 找出环的入口



1. 链表的定义

链表有几种常见类型,单向循环带头节点,单向循环不带头结点,单项非循环带头节点,单向非循环不带头结点,双向循环带头结点…
这里,我们只讲最重要最常考的两个==,双向非循环不带头结点和单项非循环不带头结点.==
一个链表就像火车一样,由一个个节点串起来,每个节点都要标出节点值和它的下一个节点的物理位置(next),之后再一次连接,就组成了链表.
如下图,链表的一个节点由节点值val和它的下一节点的位置组成

在这里插入图片描述
如下图是一个单向不循环无头结点的链表.链表的第一个节点,0x21是节点自身位置,12是节点值,0x39是下一个节点的位置,也就是第二个节点的位置.
在这里插入图片描述
链表的空间顺序,逻辑上是连续的,物理上是随机的.
而顺序表ArrayList物理上是连续存储的一块空间.

2. 链表的创建

2.1 基础创建

1.我们先简单创建一个链表,熟悉一下链表的使用,注意结尾处的this.head = listnode1,指定第一个节点为链表头节点.

 	public void createList(){
        ListNode listnode1 = new ListNode(12);
        ListNode listnode2 = new ListNode(25);
        ListNode listnode3 = new ListNode(3);
        ListNode listnode4 = new ListNode(79);
        ListNode listnode5 = new ListNode(53);
        listnode1.next = listnode2;
        listnode2.next = listnode3;
        listnode3.next = listnode4;
        listnode4.next = listnode5;
        listnode5.next = null;
        this.head = listnode1;
    }

2.2 尾插法创建头节点

尾插法就是把新节点插到链表的末尾.
如下图所示,要求插入新的节点,节点值为99.
在这里插入图片描述
首先,我们要讨论一种特殊情况,就是链表还没有节点,那么头节点就是这个插入的新节点.

ListNode listnode = new ListNode(data);
if(head == null){
    head = listnode;
}

若是节点有头节点,则就遍历链表,找到链表尾巴,把新节点插到尾巴后面即可.
那么怎么找到链表的尾巴呢,从那面那幅图我们看到,链表尾巴的next为null,所以从头开始遍历,直到节点的next为null.就把新节点插到这个节点后面.

			ListNode cur = head;
            while(cur.next != null){
                cur = cur.next;
            }
            cur.next = listnode;

完整代码如下

	public void addLast(int data){
        ListNode listnode = new ListNode(data);
        if(head == null){
            head = listnode;
        }else{
            ListNode cur = head;
            while(cur.next != null){
                cur = cur.next;
            }
            cur.next = listnode;
            listnode.next = null;
        }
    }

执行结果为
在这里插入图片描述

2.3 头插法

如下图,把节点值为99的节点插在链表头部,即node.next = head;head改为node,这里没有解引用,不用判断head == null.
在这里插入图片描述

	public void addFirst(int data){
        ListNode node = new ListNode(data);
        node.next = head;
        head = node;
    }

在这里插入图片描述

3. 链表的基础方法

3.1 获取链表长度

遍历一遍链表,从head开始,注意结束位置,是cur != null,注意别落下那个cur.next == null的最后一个节点.

	public int size(){
        int count = 0;
        ListNode cur = head;
        while(cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }

3.2 是否包含某个节点

注意循环条件,cur != null

	public boolean contain(int key){
        ListNode cur = this.head;
        while(cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

3.3 在任意坐标处插入节点

为了保证程序在遇到不合法的输入时崩溃,我们在启动程序之前就要考虑好所有可能输入值会出现的结果.
void addIndex(int index, int value)
首先,若是选定的坐标小于0,或者超出给定范围,程序要报错,防止程序崩溃.

		if(index < 0 || index > size()){
            throw new WrongIndexException("选择的坐标不合法");
        }

其次,当给定坐标是0时,头插此节点,给定坐标是size()时,尾插此节点

	   if(index == 0){
            addFirst(value);
        }else if(index == size()){
            addLast(value);
        }

若都不是,如下图,在坐标1处插入值为100的节点.
在这里插入图片描述
这里就要修改99的next指向和100的next指向.也就是找到坐标处的前一个位置cur,如下图在这里插入图片描述
注意这里我们不可以先修改cur的next,如下代码,如果先修改cur的next,node的next就找不到了.

cur.next = node;
node.next = cur.next

正确的写法如下

node.next = cur.next;
cur.next = node;

完整代码如下

	public void addIndex(int index,int value){
        if(index < 0 || index > size()){
            throw new WrongIndexException("选择的坐标不合法");
        }
        if(index == 0){
            addFirst(value);
        }else if(index == size()){
            addLast(value);
        }else{
            ListNode cur = head;
            while((index-1) > 0){
                cur = cur.next;
                index--;
            }
            ListNode node = new ListNode(value);
            node.next = cur.next;
            cur.next = node;
        }
    }

3.4 删除第一个值为key的节点

首先,我们需要找到值为key的节点的前一个结点,改变这个节点的next指向,就可以删除值为key的节点.
这里要考虑几个特殊情况
1.head 为 null,链表为空链表,直接返回

		if (head == null) {
            System.out.println("链表为空链表,无法删除");
            return;
        }

2.我们遍历的节点值,是从head.next开始的,所以要特别关注一下head的值是不是key,head.val 为key,直接head = head.next;

		ListNode cur = head;
        //如果头节点的值 == key
        if(cur.val == key){
            head = head.next;
            return;
        }

之后,正常找,找到值为key的节点的前一个结点.

		while (cur.next != null) {
            if (cur.next.val == key) {
                break;
            }
            cur = cur.next;
        }

如果遍历完毕,找到了,修改前一个结点的next指向,没找到,直接返回

		if(cur.next != null){//正常找到,改变cur的next指向即可
            cur.next = cur.next.next;
        }else{               
            System.out.println("未找到要删除的节点");//没找到节点,直接返回
            return;
        }

完整代码如下

	public void deleteKey(int key) {
        if (head == null) {
            System.out.println("链表为空链表,无法删除");
            return;
        }
        ListNode cur = head;
        //如果头节点的值 == key
        if(cur.val == key){
            head = head.next;
            return;
        }
            //找到值为key的节点的前一个结点,找到后退出循环
        while (cur.next != null) {
            if (cur.next.val == key) {
                break;
            }
            cur = cur.next;
        }
        //如果刚好是最后一个节点值为key,删除最后一个节点,即改变preCur的next指向
        if(cur.next != null){//正常找到,改变cur的next指向即可
            cur.next = cur.next.next;
        }else{               
            System.out.println("未找到要删除的节点");//没找到节点,直接返回
            return;
        }
    }

3.5 删除所有节点值为key的节点

这道题有点难想,我们需要找到每一个节点为key的节点的前一个结点,改变节点的next指向,进而删除节点.
如下图,删除所有值为12的节点.从第二个节点开始遍历,若是cur的值为key,便修改preCur的next指向.否则,cur和preCur往后走.
在这里插入图片描述
第二个节点值不为key,cur,preCur往后走.如下图
在这里插入图片描述
cur的值为key,便通过修改preCur的next指向来删除第三个节点.preCur.next = cur.next;cur向后移动.注意这里preCur是记录链表cur节点的前一个节点,所以这里preCur不用变.

 			if(cur.val == key){
                preCur.next = cur.next;
                cur = cur.next;
              }

如下图
在这里插入图片描述
之后的操作重复,不做赘述.
最后,注意我们还没比较头节点的值是不是key,如果符合的话,直接head == head.next;

		 if(head.val == key){
            head = head.next;
        }

完整代码如下.

	public void deleteAllKey(int key){
        if(head == null){
            System.out.println("链表为空链表");
            return;
        }
        ListNode cur = head.next;
        ListNode preCur = head;
        while(cur != null){
            if(cur.val == key){
                preCur.next = cur.next;
                cur = cur.next;
            }else{
                preCur = cur;
                cur = cur.next;
            }
        }
        if(head.val == key){
            head = head.next;
        }
    }

4. 链表的进阶方法

4.1 反转链表

如下图所示,将链表反转
在这里插入图片描述
思路是使后一节点的next指向前一节点,但要事先保留后一节点的next节点.
先考虑两个特殊情况,空链表和只有一个节点的链表直接返回就可.

		if(head == null){
            return ;
        }
        if(head.next == null){
            return ;
        }

定义cur = head.next,preCur = head,nextCur = cur.next;如下图
在这里插入图片描述

修改第二个节点指向

		    nextCur = cur.next;
            cur.next = preCur;
            preCur = cur;
            cur = nextCur;

如下图,修完完第二个节点的next指向,cur = nextCur.一定要事先记录好cur的原next节点.
在这里插入图片描述
之后,再次进入循环,记录完cur的next节点后,修改cur的next指向.
最后全部修改完毕,如下图注意处理头节点和尾节点.
原头节点12的next置为空,之后head 改为preCur

在这里插入图片描述
完整代码如下

	public void reverseList(){
        if(head == null){
            return ;
        }
        if(head.next == null){
            return ;
        }
        ListNode preCur = head;
        ListNode cur = head.next;
        ListNode nextCur = null;
        while(cur != null){
            nextCur = cur.next;
            cur.next = preCur;
            preCur = cur;
            cur = nextCur;
        }
        head.next = null;
        head = preCur;
    }

执行结果如下
在这里插入图片描述

4.2 找出中间节点

这个我们通过快慢节点的方法找出中间节点.快节点一次走两步,慢节点一次走一步,快节点走到终点的时候,列出方程,2x = s,x = s/2,则慢节点走到了中间位置.
首先,如果是空链表或者是只有一个节点,直接返回head即可.

		if(head == null){
            System.out.println("链表为空链表");
            return null;
        }
        if(head.next == null){
            return head;
        }

之后,快慢节点往后走,直到fast.next = null.

		while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }

如下图,slow节点就是中间节点.
在这里插入图片描述
完整代码如下

 	public ListNode getMidNode(){
        if(head == null){
            System.out.println("链表为空链表");
            return null;
        }
        if(head.next == null){
            return head;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

执行结果为
在这里插入图片描述

4.3 找出倒数第K个节点

用的方法也是快慢节点,快节点先走K-1步,之后快慢节点一起走,快节点走到终点,慢节点就到了倒数第K个节点.
如下图,找倒数第4个节点,快节点先走3步
在这里插入图片描述
之后,快慢节点一起走,直到快节点走到终点,慢节点就是倒数第四个节点.
在这里插入图片描述
首先讨论特殊情况
1.链表为空链表,直接返回null
2.K非法,小于0,或者大于链表的size().需要抛出异常.

		if(head == null){
            return null;
        }
        if(k < 0 || k > this.size()){
            throw new WrongIndexException("输入的坐标非法");
        }

正常情况,fast先走K-1,之后fast,slow一起走

	ListNode fast = head;
        ListNode slow = head;
        while(k-1 > 0){
            fast = fast.next;
            k--;
        }
        while(fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }

完整代码如下

public ListNode LastKthNode(int k){
        if(head == null){
            return null;
        }
        if(k < 0 || k > this.size()){
            throw new WrongIndexException("输入的坐标非法");
        }
        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;
    }

4.4 用数值x分割列表

链表小于数x的节点放左边,大于x的节点放右边,节点相对顺序要求保持不变.
如下图,要求节点值小于30的节点放左边,节点值大于30的节点放右边.保持相对位置不变,例如第二个链表中,54要在44的前面,这个相对位置不能变.
在这里插入图片描述
这里我们需要实现两个链表,第一个链表装小于30的节点,第二个链表装大于30的节点,最后再将两个链表连起来,就可以啦~
所以呢,我们这里要准备第一个节点的尾节点be和第二个节点的头节点as,用于两个链表的连接.准备第一个链表的头节点,用于新链表的遍历,准备第二个节点的尾节点,给他的next置空.如下图所示.
在这里插入图片描述
首先,找到第一个小于30的节点,作为链表1的头节点bs,之后小于30的节点往后连.

		 if(cur.val < x){
                if(bs == null){
                    bs = cur;
                    be = cur;
                }else{
                    be.next = cur;
                    be = be.next;
                }
            }

找到第一个大于30的节点,作为链表2的头节点,之后大于30的节点往后连.

			else{
                if(as == null){
                    as = cur;
                    ae = cur;
                }else{
                    ae.next = cur;
                    ae = ae.next;
                }
            }

最后将这两个链表连起来.
这里要考虑一个特殊情况,原链表里如果没有小于30的节点,bs = null,直接返回as就行,记得要把ae的next置空.

		if(bs == null){
           if(ae != null){
               ae.next = null;
           }
            return as;
        }

正常情况直接连就可以.

		else{
            be.next = as;
            if(ae != null){
                ae.next = null;
            }
            return bs;
        }

完整代码如下

	public ListNode seperateList(int x){
        ListNode bs = null;
        ListNode be = null;
        ListNode as = null;
        ListNode ae = null;
        ListNode cur = head;
        while(cur != null){
            if(cur.val < x){
                if(bs == null){
                    bs = cur;
                    be = cur;
                }else{
                    be.next = cur;
                    be = be.next;
                }
            }else{
                if(as == null){
                    as = cur;
                    ae = cur;
                }else{
                    ae.next = cur;
                    ae = ae.next;
                }
            }
            cur = cur.next;
        }
        if(bs == null){
           if(ae != null){
               ae.next = null;
           }
            return as;
        }else{
            be.next = as;
            if(ae != null){
                ae.next = null;
            }
            return bs;
        }
    }

4.5 判断是否为回文链表

如下图,两个链表都为回文链表.
在这里插入图片描述
在这里插入图片描述

如何判断链表是否是回文链表呢?
我们可以发现,回文链表的首尾节点到中间节点的值一直是相同的.我们首先找到中间节点,反转后面的链表,如下图,我们从头节点和尾节点向中间遍历,如果节点值一直相同,则为回文链表,否则不是.
在这里插入图片描述
找到中间节点,之前的代码说过这个,用什么方法来着?---------------------------快慢指针,slow为中间节点.

		ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }

反转中间节点之后的链表

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

被反转后的链表如下图.
在这里插入图片描述
在这里插入图片描述

这里的preCur就是尾节点了.
之后从首尾向中间遍历节点,值不同返回false,直到首尾节点都走到了中间节点或者preCur.next = head,循环结束.

		while(preCur != head){
            if(preCur.val != head.val){
                return false;
            }
            if(preCur.next == head){
                return true;
            }
            preCur = preCur.next;
            head = head.next;
        }
        return false;

完整代码

	public boolean palindromeLinkedList(){
        if(head == null){
            return false;
        }
        if(head.next == null){
            return true;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode cur = slow.next;
        ListNode preCur = slow;
        while(cur != null){
            ListNode curNext = cur.next;
            cur.next = preCur;
            preCur = cur;
            cur = curNext;
        }
        while(preCur != head){
            if(preCur.val != head.val){
                return false;
            }
            if(preCur.next == head){
                return true;
            }
            preCur = preCur.next;
            head = head.next;
        }
        return false;
    }

4.6 判断链表是否有环

如下图,链表最后一个节点指向前面的某个节点,则链表中出现了环.
在这里插入图片描述
如何判断链表是否有环呢?
我们采用快慢指针的方法,由于链表中有环,一个走两步,一个走一步,两个指针总会指向同一个节点.
完整代码如下.

	public boolean linkedListHasRing(){
        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;
    }

1. 附加 给链表添加环

最后一个节点的next指向前面的某个节点.

	public void createRing(){
        ListNode cur = head;
        while(cur.next != null){
            cur = cur.next;
        }
        cur.next = head.next;
    }

4.7 找出环的入口

这里用到了数学里的解方程,如下图,
慢指针的路程*2 = 快指针的路程
推导出:头节点到环入口的距离 = 相遇点到环入口的距离

在这里插入图片描述
所以,先找到相遇点,让指针分别从头节点和相遇点往中间走,直到两指针相遇,相遇的点就是环的入口.

找到相遇点

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

链表有环的话,让两个指针从头节点和相遇点往中间走,相遇的点为环的入口.

		ListNode cur = head;
        while(cur != slow){
            cur = cur.next;
            slow = slow = slow.next;
        }
        return cur;

完整代码

	public ListNode inletOfRing(){
        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;
        }
        ListNode cur = head;
        while(cur != slow){
            cur = cur.next;
            slow = slow = slow.next;
        }
        return cur;
    }

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

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

相关文章

【qsort函数实现】

前言&#xff1a; 首先在进行讲解之前&#xff0c;我们先进行对函数的一些相关介绍&#xff0c;方便大家更好的理解它。 目录函数介绍函数实现函数介绍 第一步&#xff1a; 我们可以先查询知道函数的使用方法&#xff1a; void qsort (void* base, size_t num, size_t size,i…

二级路由器的设置上网

设置步骤 &#xff08;简单记录一下&#xff09; 前提条件&#xff1a;一级路由器网络正常&#xff0c;这里主要是使用 lan 口&#xff0c;需要确保各个 lan 口正常&#xff0c;我家里是移动公司的路由器&#xff0c;有一个 lan 端口专门给电视用的&#xff0c;选择它来接二级…

ZigBee 3.0实战教程-Silicon Labs EFR32+EmberZnet-5-01:片上资源详解

【源码、文档、软件、硬件、技术交流、技术支持&#xff0c;入口见文末】 【所有相关IDE、SDK和例程源码均可从群文件免费获取&#xff0c;免安装&#xff0c;解压即用】 持续更新中&#xff0c;欢迎关注&#xff01; 前面《ZigBee 3.0实战教程-Silicon Labs EFR32EmberZnet-2…

一个无线鼠标的HID Report Desc

HID设备是USB规范定义的设备类型之一&#xff0c;其分类号为0x03. 关于USB设备类型定义&#xff0c;可参见本站&#xff1a;USB设备类型定义 - USB中文网 HID设备除了用于专门的输入输出设备外&#xff0c;有时也与其它的设备类型组合成一个复杂的设备。如对于UVC摄像头设备&a…

干货!数据智能作为先进生产力,如何助力销售效能提升?

存量竞争市场中&#xff0c;企业需要通过精细化运营提升客户价值与 ROI。数据智能作为先进生产力&#xff0c;在搜索、广告、推荐业务方面已经足够成熟&#xff0c;那么它是如何助力销售提升效能呢&#xff1f;本文将详细介绍。点击文末“阅读原文”即可观看完整版直播回放&…

中科大2007年复试机试题

中科大2007年复试机试题 文章目录中科大2007年复试机试题第一题问题描述解题思路及代码第二题问题描述解题思路及代码第三题问题描述解题思路及代码第四题问题描述解题思路及代码第一题 问题描述 编写程序&#xff0c;判断给定数字是否是回文数。 示例 1 输入&#xff1a;12…

博主的心肝宝贝

写的不错的文档 Sql(Structured Query Language)语句笔记_sky wide的博客-CSDN博客常用sql语句总结https://blog.csdn.net/qq_44652591/article/details/127545318Linux samba服务配置_sky wide的博客-CSDN博客_linux samba配置但是&#xff0c;注意后面公司的需求&#xff0c;…

Docker部署Jenkins

系列文章目录 Docker部署 registry Docker搭建 svn Docker部署 Harbor Docker 部署SQL Server 2017 Docker 安装 MS SqlServer Docker部署 Oracle12c Docker部署Jenkins Docker部署Jenkins系列文章目录前言一、启动docker&#xff0c;下载Jenkins镜像文件二、创建Jenkins挂载目…

fastjson 1.2.24漏洞复现

原理 fastjson由于没有对type进行安全性验证&#xff0c;使攻击者传入危险的类&#xff0c;通过rmi服务指定的攻击机上的恶意class文件&#xff0c;导致命令执行。 版本 1.2.24 环境准备 靶机&#xff1a;ubuntu&#xff0c;192.168.52.129 攻击机&#xff1a;kali&#…

数组的定义和使用

一、一维数组的定义、初始化 1. 一维数组的定义 元素类型 数组名[常量表达式]&#xff1b; &#xff08;1&#xff09;一维数组是由元素类型、数组名和长度组成的构造类型。 &#xff08;2&#xff09;数组名必须符合C标识符规则。 &#xff08;3&#xff09;常量表…

【ONE·C || 初识C语言 】

总言 C语言初步认识。 文章目录总言1、main函数的三种写法2、常见数据类型&#xff1a;内置类型、自定义类型2.1、内置类型总述2.2、内置类型大小计算(32/64)2.3、计算机基本存储单位3、常量、变量3.1、变量3.1.1、变量的分类&#xff1a;全局变量、局部变量3.1.2、变量的作用域…

XL1278-SMT无线模块介绍

XL1278-SMT无线模块简介XL1278-SMT无线模块是采用SEMTECH公司最新的LoRaTM调制技术的无线芯片&#xff0c;该模块除传统的GFSK调制技术外&#xff0c;还采用了LoRa&#xff08;远程&#xff09;扩频技术&#xff0c;具有超远距离扩频通讯&#xff0c;高抗干扰性和最大限度的减小…

SAP 成本组件分割价格详解

本文整理CKM3中“CV成本组件”视图下各项成本的价格取值逻辑。 SELECTTCKH3~ELEMT ”成本构成号TCKH3~EL_HV ”全部成本TCKH1~TXELE ”成本构成名称TKEVA04~WERTKOMP1 ”字段名FROM TCKH3INNER JOIN TCKH1 ON TCKH1~ELEHK TCKH3~ELEHKAND T…

JavaScript 比较 和 逻辑运算符

文章目录JavaScript 比较 和 逻辑运算符比较运算符如何使用逻辑运算符条件运算符JavaScript 比较 和 逻辑运算符 比较和逻辑运算符用于测试 true 或者 false。 比较运算符 比较运算符在逻辑语句中使用&#xff0c;以测定变量或值是否相等。 x5&#xff0c;下面的表格解释了比较…

笔记本电脑连接不上wifi怎么办?看下面4种方法

WIFI可以让我们的网络运行得更快&#xff0c;尤其是对于工作来说&#xff0c;它是不可或缺的。但是有时候&#xff0c;我们明明在笔记本电脑上看到WIFI&#xff0c;但就是连接不上&#xff0c;笔记本电脑连接不上wifi怎么办&#xff1f;方法主要有下面4个&#xff01; 演示机型…

剖析valueOf方法,深入探究Integer缓存实现机制

一. 问题展现我们在面试的时候&#xff0c;面试官经常会给面试者洒出一些迷雾&#xff0c;用来迷惑面试者&#xff0c;这时往往就需要面试者掌握底层源码&#xff0c;才能对问题进行较好的回答。接下来壹哥就以Integer的缓存数组为例&#xff0c;通过分析其源码来教会大家该如何…

Linux串口测试例程

嵌入式Linux开发过程中&#xff0c;进行Linux串口测试&#xff0c;需要针对串口进行回环测试或者指定串口接收一定的数据或者指定串口发送一定的数据使用该测试用例很快验证硬件串口的稳定性和正确性。使用代码连接如下Linux串口测试例程&#xff0c;进行Linux串口测试&#xf…

爬虫逆向之字体反爬(二)、镀金的天空-字体反爬-2

趁热打铁来写字体反爬的第二篇&#xff0c;首先是题目 网页上显示的不是常规的数字&#xff0c;源码里面也是一些汉字 虽然看上去很乱&#xff0c;但是仔细观察还是能发现一些规律&#xff0c;比如&#xff1a;长 对应 2&#xff0c;思对应 1 所以这里的解题思路&#xff0c;也…

基于Python实现四大名著章节标注汉语拼音

起因很单纯&#xff0c;就是给我1年级小豆包的女儿标注三国和西游章节的汉语拼音&#xff0c;我女儿每天都朗读 &#xff0c;结果有很多字不认识&#xff0c;我爱人居然让我给标记不认识的完了手动注音......我勒个去......身为程序员的我怎么能忘记用程序实现呢&#xff0c;特…

再次战胜人类:Meta AI推出首款可以忽悠人的AI模型

文&#xff5c;ShonaCicero&#xff0c;是Meta AI提出的能够在『强权外交』游戏中超越人类的AI模型。它凭借自己"忽悠"人的能力&#xff08;模拟谈判与合作&#xff09;&#xff0c;成为游戏里的顶级高手。AI模型连外交这活儿都能得心应手了&#xff1f;没错&#xf…