单链表进阶实操:5 道常考面试题详细解析【Java 实现】

文章目录

1.统计单链表中有效节点的个数

java 复制代码
        /**
     * 获取单链表中有效节点数量,除去头节点外的节点
     *
     * @return 返回节点个数
     */
    public int getLength() {
        if (isEmpty()) { // 如果为空,则返回0
            return 0;
        } else { // 如果不为空,需要遍历
            int num = 0;
            HeroNode tempNode = this.headNode;
            do {
                tempNode = tempNode.getNext();
                num++;
            } while (tempNode.getNext() != null);
            return num;
        }
    }

2.查找单链表中倒数第k个节点【新浪面试题】

java 复制代码
        /**
     * 查找单链表中倒数第k个节点【新浪面试题】
     * 1. 先计算总节点个数
     * 2. 倒数是第k个节点,那正数是第几个?length-(k-1)==> length-k+1
     *
     * @param k 倒数第k个节点
     * @return 返回查找的节点
     */
    public HeroNode getNodeByTailK(int k) {
        int Length = this.getLength();
        int index = Length - k + 1; // 正数的下标
        // 如果单链表长度为0或者k值大于链表长度,则返回null
        if (Length == 0 || k > Length) {
            return null;
        } else { // 返回第index个节点
            HeroNode tempNode = this.headNode;
            for (int i = 1; i <= index; i++) {
                tempNode = tempNode.getNext();
            }
            return tempNode;
        }
} 

3.单链表的反转【腾讯面试题】

使用"头插法",每次将新节点插入链表的第一个有效节点位置,旧链表从头开始遍历即可,这样新链表中元素就形成了反转。

java 复制代码
        /**
    * 单链表的反转【腾讯面试题】
    * 将链表中的元素反转
    *
    * @return 返回新链表
    */
   public SingleLinkedList_Heroes reverse() {
       SingleLinkedList_Heroes reverse_linked_list = new SingleLinkedList_Heroes(); // 默认只有一个头节点
       // 1.先判断链表是否为空,如果为空,直接返回头节点即可
       if (!this.isEmpty()) {
           // 2.如果不为空,从原链表头部遍历,将元素链接到新链表头部与第一个节点直接,形成反转
           HeroNode tempNode_old = this.getHeadNode().getNext(); // 原链表的第一个有效节点
           HeroNode tempNode_head = reverse_linked_list.getHeadNode(); // 新链表头节点
           HeroNode tempNode_no1 = tempNode_head.getNext(); // 新链表第一个有效节点,一开始为null
           while (tempNode_old != null) {
               HeroNode tempNode = new HeroNode(tempNode_old); // 待插入的节点数据;这里一定要创建新节点,不能引用地址
               tempNode.setNext(tempNode_no1); // 该节点作为新链表中第一个有效节点
               tempNode_head.setNext(tempNode); // 将新链表头节点指向该节点
               tempNode_no1 = tempNode_head.getNext(); // 更新新列表第一个有效节点
               tempNode_old = tempNode_old.getNext(); // 继续遍历原链表
           }
       }
       return reverse_linked_list;
   } 

4.将单链表逆向打印【百度面试题】

方法一:先将链表元素反转再打印;

方法二:使用"栈"数据结构,将链表元素依次压入栈中,再利用栈的先入后出的特性将元素取出,形成逆序打印;

下面代码使用方法二:

java 复制代码
        /**
     * 使用栈逆序打印链表元素
     */
    public void reversePrint() {
        if (this.isEmpty()) { // 如果链表为空
            System.out.println("单链表为空!");
        } else {
            Stack<HeroNode> stack = new Stack<>(); // 初始化栈
            HeroNode tempNode = this.getHeadNode().getNext();
            // 将链表元素入栈
            while (tempNode != null) {
                stack.push(tempNode);
                tempNode = tempNode.getNext();
            }
            // 将所有元素出栈,形成逆序打印
            while (!stack.isEmpty()) {
                System.out.println(stack.pop());
            }
        }
    } 

5.将两个有序单链表合成一个有序单链表

java 复制代码
       /**                                                                                                                                                                                        
     * 静态方法,合并两个有序链表,返回新链表对象                                                                                                                                                                   
     *                                                                                                                                                                                         
     * @param list1 有序链表1                                                                                                                                                                      
     * @param list2 有序链表2                                                                                                                                                                      
     * @return 合并之后有序链表                                                                                                                                                                        
     */                                                                                                                                                                                        
    public static SingleLinkedList_Heroes mergeTwoList(SingleLinkedList_Heroes list1, SingleLinkedList_Heroes list2) {                                                                          
        // 1.判断两个链表是否为空;list1为空返回list2;list2为空返回list1;                                                                                                                                         
        if (list1.isEmpty()) {                                                                                                                                                                 
            return list2;                                                                                                                                                                      
        } else if (list2.isEmpty()) {                                                                                                                                                          
            return list1;                                                                                                                                                                      
        } else {                                                                                                                                                                               
            // 2.两者都不为空时,创建新链表,用两个指针指向list1和list2,从有效节点开始顺序遍历,直至两个指针指向null;                                                                                                                    
            SingleLinkedList_Heroes newList = new SingleLinkedList_Heroes();                                                                                                                   
            HeroNode tempNode1 = list1.getHeadNode().getNext(); // 指针一指向list1的第一个有效节点                                                                                                          
            HeroNode tempNode2 = list2.getHeadNode().getNext(); // 指针二指向list2的第一个有效节点                                                                                                          
            while (tempNode1 != null && tempNode2 != null) {   // 遍历条件:两个指针均不为null时才遍历                                                                                                         
                // 3.每次都进行比较,按照升序方式加入新链表;这里按照no编号继续比较;需要考虑相等的情况                                                                                                                                
                if (tempNode1.getNo() <= tempNode2.getNo()) { // 小数据节点排在前面                                                                                                                     
                    newList.addHero(new HeroNode(tempNode1));                                                                                                                                  
                    newList.addHero(new HeroNode(tempNode2));                                                                                                                                  
                } else {                                                                                                                                                                       
                    newList.addHero(new HeroNode(tempNode2));                                                                                                                                  
                    newList.addHero(new HeroNode(tempNode1));                                                                                                                                  
                }                                                                                                                                                                              
                tempNode1 = tempNode1.getNext();                                                                                                                                               
                tempNode2 = tempNode2.getNext();                                                                                                                                               
            }                                                                                                                                                                                  
            // 4.循环结束后,一定有其中一个链表还有剩余节点,**单独把剩下的节点循环拷贝加入新链表**。                                                                                                                                  
            // 4.1 考虑两个链表的节点数量                                                                                                                                                                 
            int num1 = list1.getLength();                                                                                                                                                      
            int num2 = list2.getLength();                                                                                                                                                      
            if (num1 == num2) { // 4.2 如果两个链表节点数量相同表示节点已遍历完毕,直接返回即可                                                                                                                            
                return newList;                                                                                                                                                                
            } else if (num1 > num2) { // 4.3 如果list1节点数量多于list2,表示list1中有剩余节点没有遍历,剩余节点数量:num1-num2;然后按照顺序插入                                                                                    
                int leave = num1 - num2;                                                                                                                                                       
                while (leave != 0) {                                                                                                                                                           
                    // 4.4 先获取尾部第leave个节点,注意需要new新节点                                                                                                                                           
                    HeroNode heroNode = new HeroNode(list1.getNodeByTailK(leave));                                                                                                             
                    // 4.5 再按照no值插入新链表中                                                                                                                                                        
                    newList.addHeroByOrder(heroNode);                                                                                                                                          
                    leave--;                                                                                                                                                                   
                }                                                                                                                                                                              
                return newList;                                                                                                                                                                
            } else { //list2节点数量多于list1的情况,跟上面相同                                                                                                                                               
                int leave = num2 - num1;                                                                                                                                                       
                while (leave != 0) {                                                                                                                                                           
                    // 4.4 先获取尾部第leave个节点,注意需要new新节点                                                                                                                                           
                    HeroNode heroNode = new HeroNode(list2.getNodeByTailK(leave));                                                                                                             
                    // 4.5 再按照no值插入新链表中                                                                                                                                                        
                    newList.addHeroByOrder(heroNode);                                                                                                                                          
                    leave--;                                                                                                                                                                   
                }                                                                                                                                                                              
                return newList;                                                                                                                                                                
            }                                                                                                                                                                                  
        }                                                                                                                                                                                       ``` 
相关推荐
光依旧14 分钟前
MCP实战手记系列(五):让工具返回一个能点的界面(文末附github源码链接)
java·spring ai·前端集成·mcp·mcp apps
APIshop19 分钟前
淘宝选品接口实战:从召回、详情、佣金到转链的 Java 接入笔记
java
雨落在了我的手上30 分钟前
Java数据结构(十四):Map和Set
数据结构
码行山野赴时序归途34 分钟前
链表家族收官篇:循环链表
c语言·开发语言·数据结构·链表
泡茶喝茶写代码34 分钟前
量化数据进阶:多维实战篇(第 11 篇):历史涨跌停价:涨跌停序列与止损线测算
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
景熙55231 小时前
单体项目编写思路和落地形式
java·开发语言
Ivanqhz1 小时前
Slope One 算法详解:与矩阵分解、共现矩阵的异同
java·服务器·网络·人工智能·深度学习
Bs_MoneyMagnet1 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
万物智能1 小时前
波形发生AD9833模块配置—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
java
计算机毕设定制辅导-无忧学长1 小时前
《基于SpringBoot的未成年人健康知识科普平台的设计与实现》
java·开发语言·vue.js·spring boot·未成年人健康知识科普平台