代码随想录—力扣算法题:707设计链表.Java版(示例代码与导图详解)

news2025/1/21 20:17:05

版本说明

当前版本号[20230818]。

版本修改说明
20230818初版

目录

文章目录

  • 版本说明
  • 目录
  • 707.设计链表
    • 思路
      • 获取链表第index个节点的数值
      • 在链表的最前面插入一个节点
      • 在链表的最后面插入一个节点
      • 在链表第index个节点前面插入一个节点
      • 删除链表的第index个节点
    • 单链表角度
    • 总结

707.设计链表

力扣题目链接
更多内容可点击此处跳转到代码随想录,看原版文件

题意:

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

image-20230817200854967

思路

如果对链表的基础知识还不太懂和对链表的虚拟头结点不清楚,,可以看这篇文章:关于链表,你该了解这些!

删除链表节点:

image-20230818144606050

添加链表节点:

image-20230818144636451

这道题目设计链表的五个接口:

  • 获取链表第index个节点的数值
  • 在链表的最前面插入一个节点
  • 在链表的最后面插入一个节点
  • 在链表第index个节点前面插入一个节点
  • 删除链表的第index个节点

可以说这五个接口,已经覆盖了链表的常见操作,是练习链表操作非常好的一道题目

我们也将从这五个接口中,讲解每一个接口的思路让大家对本题有更加清晰的认知。

获取链表第index个节点的数值

  1. 检查index是否有效,如果index小于0或大于等于链表长度,则返回-1。

  2. 从头结点开始,定义一个指针currentNode指向head节点(虚拟头结点的下一个节点)。

    【为什么要定义指针currentNode呢? 答:因为我们操作完链表后,要返回头结点,如果直接操作头结点,那么返回头结点的时候头结点的值已经改了。】

  3. 通过循环遍历,将currentNode指针移动index次,直到达到目标位置。

  4. 循环过程中,每次将currentNode指针指向currentNode的下一个节点即currentNode = currentNode.next。

  5. 循环结束后,currentNode指针指向第index个节点。

  6. 返回currentNode的值,即currentNode.val,作为结果。

image-20230818161709180

在链表的最前面插入一个节点

  1. 创建一个新的节点,将值设置为val。

  2. 将新节点的next指针指向当前的头节点,即新节点的next指向原来的第一个节点。

    image-20230818162005456

    注:此时我们新建了一个新的结点new node ,然后形成下图的趋势去插入结点

    image-20230818162403398

    ​ 那在指示下,我们就会发现head所代表的下一个区域无法表达出来,因为:原先的head区域我们是可以用 dymghead - > next 来表示了,但又因为我们已经用其表示new node 了,已经修改了 dymghead - > next 的值去了,就无法再表达 head 的区域了。

    image-20230818162727448

从上面的教训我们就知道,应该先表达new node 和 head 的关系,再表达 dymghead , 才不会出现修改了值,无法表达的情况。

于是先 表达 new node - > next = dymghead - > next , 再表达dymghead - > next= new node ,即可。

image-20230818163422254

3.将链表的头节点指向新节点,使新节点成为新的头节点。

在链表的最后面插入一个节点

  1. 创建一个新的节点,将值设置为val。
  2. 如果链表为空,即**链表的头节点为null,将链表的头节点指向新节点。**新节点成为链表的唯一节点。
  3. 如果链表不为空,找到链表的最后一个节点。从头节点开始遍历链表,通过next指针逐个访问节点,直到找到最后一个节点。
  4. 将最后一个节点的next指针指向新节点,将新节点插入到链表的最后一个位置。

image-20230818164252981

在链表第index个节点前面插入一个节点

  1. 创建一个新的节点,将值设置为val。
  2. 检查index的值是否为0,如果是0,则直接调用addAtHead(val)方法,在链表的头部插入节点。
  3. 如果index大于0,需要找到链表的第index-1个节点。
  4. 从头节点开始遍历链表,通过next指针逐个访问节点,直到找到第index-1个节点。
  5. 将新节点的next指针指向第index个节点。
  6. 将第index-1个节点的next指针指向新节点。

image-20230818165850534

删除链表的第index个节点

  1. 检查index是否有效,如果index小于0或大于等于链表长度,则直接返回,不进行删除操作。
  2. 如果index有效,分为两种情况处理删除操作:
    • 如果index为0,即要删除的是链表的第一个节点。将链表的头节点指向第二个节点,即头节点的next指针所指向的节点。
    • 如果index不为0,需要找到第index-1个节点。从头节点开始遍历链表,通过next指针逐个访问节点,直到找到第index-1个节点。
  3. 将第index-1个节点的next指针指向第index+1个节点,即跳过要删除的节点。

image-20230818170459646

链表操作的两种方式:

  1. 直接使用原来的链表来进行操作。
  2. 设置一个虚拟头结点在进行操作。

下面采用的设置一个虚拟头结点(这样更方便一些,大家看代码就会感受出来)。

单链表角度

这段代码实现了一个单链表数据结构,包括了链表的初始化、插入、删除和获取等操作。让我们逐步分析每个方法的作用:

  1. ListNode类:用来表示链表的节点,包含一个整数val表示节点的值,以及一个指向下一个节点的指针next

    //单链表
    class ListNode { // 定义链表节点类
        int val; // 节点值
        ListNode next; // 指向下一个节点的指针
    
        ListNode() {
        } // 默认构造函数
    
        ListNode(int val) { // 带参构造函数
            this.val = val;
        }
    }
    
  2. MyLinkedList类:实际上就是单链表的实现,包含以下几个核心属性和方法:

    • size:保存链表中节点的个数

    • head:虚拟头结点,作为链表的起始位置

    • MyLinkedList():构造函数,用来初始化链表。将size设置为0,并创建一个值为0的虚拟头结点。

          int size; // 链表元素个数
          //虚拟头结点
          ListNode head; // 虚拟头节点
      
          //初始化链表
          public MyLinkedList() {  // 构造函数
              size = 0;  // 初始化链表大小为0
              head = new ListNode(0);  // 创建一个值为0的虚拟头节点
          }
      
    • get(int index):**获取第index个节点的值。**如果index越界,返回-1。从头结点开始遍历链表,找到第index+1个节点,并返回其值。

     //获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点
        public int get(int index) {  // 获取链表中第index个节点的值
            //如果index非法,返回-1
            if (index < 0 || index >= size) {  // 如果index小于0或大于等于链表大小,则索引非法,返回-1
                return -1;
            }
            ListNode currentNode = head;  // 从头结点开始遍历链表
            //包含一个虚拟头节点,所以查找第 index+1 个节点
            for (int i = 0; i <= index; i++) {  // 遍历找到第index+1个节点(包括虚拟头节点)
                currentNode = currentNode.next;
            }
            return currentNode.val;  // 返回第index个节点的值
        }
    
    • addAtHead(int val):在链表的最前面插入一个节点,等价于在第0个元素前添加。调用addAtIndex(0, val)方法实现。
    • addAtTail(int val):在链表的最后插入一个节点,等价于在末尾元素后添加。调用addAtIndex(size, val)方法实现。
        //在链表最前面插入一个节点,等价于在第0个元素前添加
        public void addAtHead(int val) {  // 在链表最前面插入一个节点
            addAtIndex(0, val);  // 调用addAtIndex方法,在第0个位置插入节点
        }
    
        //在链表的最后插入一个节点,等价于在(末尾+1)个元素前添加
        public void addAtTail(int val) {  // 在链表最后插入一个节点
            addAtIndex(size, val);  // 调用addAtIndex方法,在末尾位置插入节点
        }
    
    • addAtIndex(int index, int val):在第index个节点之前插入一个新节点,如果index等于链表的长度,则插入为尾结点;如果index大于链表的长度,不进行插入。首先进行边界判断,然后找到第index个节点的前驱节点,创建一个新的节点并将其插入到合适的位置。
     // 在第 index 个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
    // 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点
    // 如果 index 大于链表的长度,则返回空
        public void addAtIndex(int index, int val) {  // 在第index个节点之前插入一个新节点
            if (index > size) {  // 如果index大于链表大小,不进行插入,直接返回
                return;
            }
            if (index < 0) {  // 如果index小于0,将index调整为0
                index = 0;
            }
            size++;  // 链表大小加1
            //找到要插入节点的前驱
            ListNode pred = head;  // 找到要插入节点的前驱节点,从头结点开始遍历链表
            for (int i = 0; i < index; i++) {  // 遍历找到第index个节点的前驱节点
                pred = pred.next;
            }
            ListNode toAdd = new ListNode(val);  // 创建一个新的节点
            toAdd.next = pred.next;  // 将新节点的next指针指向前驱节点的next指针指向的节点
            pred.next = toAdd;  // 将前驱节点的next指针指向新节点,实现节点插入
        }
    
    • deleteAtIndex(int index):删除第index个节点。如果index越界,不进行删除。首先进行边界判断,然后找到第index个节点的前驱节点,将其next指针指向下一个节点的next指针,实现节点的删除。
 //删除第index个节点
    public void deleteAtIndex(int index) {  // 删除第index个节点
        if (index < 0 || index >= size) {  // 如果index小于0或大于等于链表大小,不进行删除,直接返回
            return; 
        }
        size--;  // 链表大小减1
        if (index == 0) {  // 如果要删除的是头结点
            head = head.next;  // 将头结点指向下一个节点即可完成删除操作
            return;
        }
        ListNode pred = head;  // 找到要删除节点的前驱节点,从头结点开始遍历链表
        for (int i = 0; i < index; i++) {  // 遍历找到第index个节点的前驱节点
            pred = pred.next;
        }
        pred.next = pred.next.next;  // 将前驱节点的next指针指向要删除节点的下一个节点,实现节点的删除
    }

这段代码实现了基本的单链表操作,并提供了对链表进行插入、删除和获取操作的接口。可以用来构建和操作一个链表数据结构。

单链表示例代码:

//单链表
class ListNode { // 定义链表节点类
    int val; // 节点值
    ListNode next; // 指向下一个节点的指针

    ListNode() {
    } // 默认构造函数

    ListNode(int val) { // 带参构造函数
        this.val = val;
    }
}

class MyLinkedList { // 定义链表类
    //size存储链表元素的个数
    int size; // 链表元素个数
    //虚拟头结点
    ListNode head; // 虚拟头节点

    //初始化链表
    public MyLinkedList() {  // 构造函数
        size = 0;  // 初始化链表大小为0
        head = new ListNode(0);  // 创建一个值为0的虚拟头节点
    }

    //获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点
    public int get(int index) {  // 获取链表中第index个节点的值
        //如果index非法,返回-1
        if (index < 0 || index >= size) {  // 如果index小于0或大于等于链表大小,则索引非法,返回-1
            return -1;
        }
        ListNode currentNode = head;  // 从头结点开始遍历链表
        //包含一个虚拟头节点,所以查找第 index+1 个节点
        for (int i = 0; i <= index; i++) {  // 遍历找到第index+1个节点(包括虚拟头节点)
            currentNode = currentNode.next;
        }
        return currentNode.val;  // 返回第index个节点的值
    }

    //在链表最前面插入一个节点,等价于在第0个元素前添加
    public void addAtHead(int val) {  // 在链表最前面插入一个节点
        addAtIndex(0, val);  // 调用addAtIndex方法,在第0个位置插入节点
    }

    //在链表的最后插入一个节点,等价于在(末尾+1)个元素前添加
    public void addAtTail(int val) {  // 在链表最后插入一个节点
        addAtIndex(size, val);  // 调用addAtIndex方法,在末尾位置插入节点
    }

 // 在第 index 个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果 index 大于链表的长度,则返回空
    public void addAtIndex(int index, int val) {  // 在第index个节点之前插入一个新节点
        if (index > size) {  // 如果index大于链表大小,不进行插入,直接返回
            return;
        }
        if (index < 0) {  // 如果index小于0,将index调整为0
            index = 0;
        }
        size++;  // 链表大小加1
        //找到要插入节点的前驱
        ListNode pred = head;  // 找到要插入节点的前驱节点,从头结点开始遍历链表
        for (int i = 0; i < index; i++) {  // 遍历找到第index个节点的前驱节点
            pred = pred.next;
        }
        ListNode toAdd = new ListNode(val);  // 创建一个新的节点
        toAdd.next = pred.next;  // 将新节点的next指针指向前驱节点的next指针指向的节点
        pred.next = toAdd;  // 将前驱节点的next指针指向新节点,实现节点插入
    }

    //删除第index个节点
    public void deleteAtIndex(int index) {  // 删除第index个节点
        if (index < 0 || index >= size) {  // 如果index小于0或大于等于链表大小,不进行删除,直接返回
            return;
        }
        size--;  // 链表大小减1
        if (index == 0) {  // 如果要删除的是头结点
            head = head.next;  // 将头结点指向下一个节点即可完成删除操作
            return;
        }
        ListNode pred = head;  // 找到要删除节点的前驱节点,从头结点开始遍历链表
        for (int i = 0; i < index; i++) {  // 遍历找到第index个节点的前驱节点
            pred = pred.next;
        }
        pred.next = pred.next.next;  // 将前驱节点的next指针指向要删除节点的下一个节点,实现节点的删除
    }

总结

针对这个题目,可以使用一个单链表的数据结构来实现所需的功能。

首先,需要定义一个链表节点的类,节点包含一个值和一个指向下一个节点的指针。

接下来,可以在链表类中实现以下功能:

  1. get(index):从头节点开始遍历链表,直到找到第 index 个节点,然后返回该节点的值。如果遍历过程中超出了链表的长度,则返回 -1。
  2. addAtHead(val):创建一个新的节点,将新节点的指针指向原来的头节点,然后将头指针指向新节点。
  3. addAtTail(val):从头节点开始遍历链表,直到找到最后一个节点,将新节点追加到最后一个节点的指针上。
  4. addAtIndex(index, val):如果 index 小于等于 0,则调用 addAtHead(val) 方法;如果 index 等于链表的长度,则调用 addAtTail(val) 方法;如果 index 大于链表长度,则不进行任何操作;否则,从头节点开始遍历链表,找到第 index - 1 个节点,然后创建一个新节点,将新节点的指针指向原来第 index 个节点的指针,再将第 index - 1 个节点的指针指向新节点。
  5. deleteAtIndex(index):如果 index 小于 0 或者大于等于链表的长度,则不进行任何操作;如果 index 等于 0,则将头指针指向第二个节点;否则,从头节点开始遍历链表,找到第 index - 1 个节点,将其指针指向第 index + 1 个节点。

以上就是分析解题思路的主要步骤。实际编写代码时,需要根据具体语言的特点进行实现,并考虑一些边界条件的处理。

单链表与双链表示例代码:

//双链表
class ListNode{
    int val;
    ListNode next,prev;
    ListNode() {};
    ListNode(int val){
        this.val = val;
    }
}


class MyLinkedList {  

    //记录链表中元素的数量
    int size;
    //记录链表的虚拟头结点和尾结点
    ListNode head,tail;
    
    public MyLinkedList() {
        //初始化操作
        this.size = 0;
        this.head = new ListNode(0);
        this.tail = new ListNode(0);
        //这一步非常关键,否则在加入头结点的操作中会出现null.next的错误!!!
        head.next=tail;
        tail.prev=head;
    }
    
    public int get(int index) {
        //判断index是否有效
        if(index<0 || index>=size){
            return -1;
        }
        ListNode cur = this.head;
        //判断是哪一边遍历时间更短
        if(index >= size / 2){
            //tail开始
            cur = tail;
            for(int i=0; i< size-index; i++){
                cur = cur.prev;
            }
        }else{
            for(int i=0; i<= index; i++){
                cur = cur.next; 
            }
        }
        return cur.val;
    }
    
    public void addAtHead(int val) {
        //等价于在第0个元素前添加
        addAtIndex(0,val);
    }
    
    public void addAtTail(int val) {
        //等价于在最后一个元素(null)前添加
        addAtIndex(size,val);
    }
    
    public void addAtIndex(int index, int val) {
        //index大于链表长度
        if(index>size){
            return;
        }
        //index小于0
        if(index<0){
            index = 0;
        }
        size++;
        //找到前驱
        ListNode pre = this.head;
        for(int i=0; i<index; i++){
            pre = pre.next;
        }
        //新建结点
        ListNode newNode = new ListNode(val);
        newNode.next = pre.next;
        pre.next.prev = newNode;
        newNode.prev = pre;
        pre.next = newNode;
        
    }
    
    public void deleteAtIndex(int index) {
        //判断索引是否有效
        if(index<0 || index>=size){
            return;
        }
        //删除操作
        size--;
        ListNode pre = this.head;
        for(int i=0; i<index; i++){
            pre = pre.next;
        }
        pre.next.next.prev = pre;
        pre.next = pre.next.next;
    }
}
new ListNode(val);
        newNode.next = pre.next;
        pre.next.prev = newNode;
        newNode.prev = pre;
        pre.next = newNode;
        
    }
    
    public void deleteAtIndex(int index) {
        //判断索引是否有效
        if(index<0 || index>=size){
            return;
        }
        //删除操作
        size--;
        ListNode pre = this.head;
        for(int i=0; i<index; i++){
            pre = pre.next;
        }
        pre.next.next.prev = pre;
        pre.next = pre.next.next;
    }
}

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

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

相关文章

STM32入门——IIC通讯

江科大STM32学习记录 I2C通信 I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线两根通信线&#xff1a;SCL&#xff08;Serial Clock&#xff09;、SDA&#xff08;Serial Data&#xff09;同步&#xff0c;半双工带数据应答支持总线挂载多设备…

Python“牵手”lazada商品评论数据采集方法,lazadaAPI申请指南

lazada平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范&#xff0c;lazadaAPI接口是指通过编程的方式&#xff0c;让开发者能够通过HTTP协议直接访问lazada平台的数据&#xff0c;包括商品信息、店铺信息、物流信息等&#xff0c;从而实现la…

程序人生:进不了大厂的测试员,究竟还有没有出路了?

金九银十的到来&#xff0c;使得许多职场人按耐不住&#xff0c;纷纷开始找寻合适的工作机会。猎头和HR们摩拳擦掌&#xff0c;争取在这两个月给今年多加点业绩。 对许多互联网人来说&#xff0c;跳槽意味着加薪&#xff0c;而对于程序员而言&#xff0c;是否能跳槽进大厂是他…

前端---需要了解浏览器相关知识--浏览器请求服务器资源---缓存

知识点1: 掘金1&#xff1a;浏览器缓存 掘金2 :浏览器缓存 一、浏览器缓存 请求&#xff08;静态资源 &#xff5c; 动态资源&#xff09; 一、缓存是什么&#xff1f; 如果没有缓存的机制 每次都要重新请求静态资源 1.从网络上的下载时间&#xff0c;肯定大于从硬盘里读的…

《树莓派4B家庭服务器搭建指南》第二十期:在树莓派运行rsnapshot, 实现对服务器数据低成本增量本地备份

title: 020《树莓派4B家庭服务器搭建指南》第二十期&#xff1a;在树莓派运行rsnapshot, 实现对服务器数据低成本增量本地备份 我的天翼云服务器有/opt 和 /usr/share/nginx两个目录, 用来存储网站的内容, 数据无价, 为了避免珍贵的数据丢失&#xff0c;我决定使用树莓派运行 …

TikTok或将于8月底关闭半闭环、速卖通或将推出“半托管”模式

《出海周报》是运营坛为外贸企业主和外贸人独家打造的重要资讯栏目&#xff0c;聚焦企业出海、海外市场动态、海外监管政策等方面&#xff0c;以简捷的方式&#xff0c;提升读者获取资讯的效率。 接下来运营坛为大家带来第15期出海周报&#xff0c;快来看看这周国内外市场发生了…

【经验】VScode远程连接Ubuntu出错的解决办法(2023年,完整的排查思路)

用VScode常常会碰到以下情况&#xff0c;Could not establish connection。 先介绍一下VScode远程连接和终端SSH连接的区别&#xff1a;终端直接用SSH连接时&#xff0c;只需要开启SSH服务&#xff0c;并消耗少量的内存即可&#xff1b;VScode连接时&#xff0c;会自动在服务器…

HCIP实验之MPLS

目录 一&#xff0c;实验题目 ​编辑 拓扑与IP地址规划如图所示 二&#xff0c;实验思路 三&#xff0c;实验步骤 3.1 私网部分IP地址配置 3.2 LSP部分配置 3.3 启动OSPF协议 3.4 启动MPLS协议 3.5 启动MPLS VPN 3.6 实现公网私网互通 3.7 配置BGP 3.8 双向重发布 …

Python软件外包开发框架

Python有许多流行的开发框架&#xff0c;用于不同类型的应用开发&#xff0c;包括Web应用、数据科学、人工智能等。以下分享一些常见的Python开发框架及其特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流…

[MySQL] — 数据类型和表的约束

目录 数据类型 数据类型分类 数值类型 tinyint类型 bit类型 小数类型 float decimal 字符串类型 char varchar char和varchar的区别 日期和时间类型 enum 和 set 表的约束 空属性 默认值 列描述 zeorfill 主键 创建表时在字段上指定主键 删除主键&#xff1a; 追…

Lnton羚通算法算力云平台在环境配置时 OpenCV 无法显示图像是什么原因?

问题&#xff1a; cv2.imshow 显示图像时报错&#xff0c;无法显示图像 0%| | 0/1 [00:00<…

IDEA连接MySQL数据库错误

说明&#xff1a;使用IDEA连接云服务器中的MySQL数据库时&#xff0c;报下面的这个错误&#xff1b; [08S01] Communications link failureThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the serve…

docker cURL error 6: Could not resolve host

场景&#xff1a; 微信小程序 获取 用户 openpid&#xff0c;在此之前&#xff0c;我需要先 "获取稳定版接口调用凭据"&#xff0c;根据手册提示的&#xff0c;要先调用 https://api.weixin.qq.com/cgi-bin/stable_token 我这边就开始了请求&#xff0c;结果返回了…

上班族的高效时间管理软件,可一直显示在电脑桌面上

在现代职场中&#xff0c;相信工作党都深有体会&#xff0c;繁忙的工作带来的压力和任务都堆积如山&#xff0c;如果没有一个良好的时间管理系统&#xff0c;我们可能会一筹莫展。而高效管理时间的好处也是显而易见的&#xff0c;它不仅可以帮助我们更好地安排工作&#xff0c;…

Linux Day09

目录 一、进程替换 二、Linux信号的使用 2.1 kill() 发送信号 2.2 signal() 改变进程对信号的响应方式 2.3 处理僵死进程 2.3.1 在信号处理函数中调用wait 2.3.2 Linux特有的 2.3.3 结果 一、进程替换 linux上创造一个新进程&#xff0c;没有create创建方法&#xf…

【Mysql】MVCC版本机制的多并发

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

Android3:布局

一。线性布局 创建项目Linear Layout Example activity_main.xml <?xml version"1.0" encoding"utf-8"?><LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"an…

微信转账警示!切莫在此时输入密码

微信已经成为我们日常生活中不可或缺的社交工具&#xff0c;通过微信红包和转账完成支付也变得非常普遍。 然而&#xff0c;正如人们常说的&#xff0c;树大招风。随着微信的广泛使用&#xff0c;骗子们也愈发猖獗&#xff0c;他们利用微信进行诈骗活动&#xff0c;使许多人遭受…

手把手教你快速使用java与cpp的互相调用

在jni的开发过程中&#xff0c;如果需要实现java和c之间的接口调用&#xff0c;就要定义一个方法来实现&#xff0c;如果有多个接口调用&#xff0c;就需要定义多个方法来实现&#xff0c;这里介绍一种抽象的接口&#xff0c;只需要分别定义一个javaCallCpp和cppCallJava方法就…

Spring框架入门以及 ioc的三种注入方式

目录 一、Spring是什么&#xff0c;它能够做什么 spring的组成 二、什么是控制反转&#xff08;或依赖注入&#xff09; 三、 如何在spring当中定义和配置一个JavaBean 四、注入方式 1.构造函数注入 2.Setter方法注入 3.自动装配 五、简单属性配置与复杂属性配置 简单…