单链表进阶实操: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;                                                                                                                                                                
            }                                                                                                                                                                                  
        }                                                                                                                                                                                       ``` 
相关推荐
斑马13916 分钟前
Linux软件编程学习笔记(五)——线程
开发语言·php
2601_9619017017 分钟前
SpringCloud2023集成Nacos2.4.3
java
玄昌盛不会编程19 分钟前
LeetCode——2091. 从数组中移除最大值和最小值
java·算法·leetcode
Rain的Java大神之路21 分钟前
如何保证接口幂等
java·经验分享·后端·面试·架构
吴声子夜歌22 分钟前
Java——数组和集合(一)
java·开发语言
Jesse_EC24 分钟前
一个看不见的字符——CRLF 如何让我的 Docker 初始化脚本"静默失踪"
java·后端
深念Y24 分钟前
Nuxt 项目 Docker 构建:从 pnpm+node 迁移到全 bun
java·前端·docker
学长毕业设计29 分钟前
基于SpringBoot的社区鲜奶订购系统的设计与实现(源码+文档+讲解视频)
java·spring boot·后端
呆呆敲代码的小Y30 分钟前
Lua 上值(UpValue)
开发语言·junit·lua·lua上值·upvalue