数据结构(Java):单链表面试OJ题

news2024/9/22 15:45:21

1、题一:获取链表倒数第k个节点

. - 力扣(LeetCode)

1.1 思路解析

此题我们使用双指针法求解。

首先,我们要知道,倒数的第k个节点,距离倒数第一个节点还需要移动k-1次

1.那么我们可以定义出两个指针,分别为fast和slow,他们初始均值均为头结点head

2.先让fast指针向后移动k-1次,slow指针保持不动。

3.接着,fast指针和slow指针同步后移直至fast指针指向最后一个节点。

4.此时,slow指针所指向的位置就是倒数第k个节点。

原理:这个解题思路的原理就是,fast指针和slow指针始终保持着k-1个移动次数,而当fast指针指向最后一个节点(即倒数第一个节点)时,那么slow指针指向的就是倒数第k个节点。

注意事项:

1.k的值是否合法 2.头指针head是否为null

1.2 代码

public int kthToLast(ListNode head, int k) {
        //当头指针为空时
        if (head == null) {
            return Integer.MAX_VALUE;
        }

        //当k的值<=0时
        ListNode cur = head;
        int size = 0;
        while (cur != null) {
            size++;
            cur = cur.next;
        }
        if (k <= 0) {
            return Integer.MAX_VALUE;
        }

        //双指针法求解
        ListNode fast = head;
        ListNode slow = head;

        //先让fast指针移动k-1次
        int count = 0;
        while (count != k - 1) {
            fast = fast.next;
            //当k值>size时(不合法),fast指针移动的k-1次中,必然会指向null
            if (fast == null) {
                return Integer.MAX_VALUE;
            }
            count++;
        }

        //slow和fast同步后移,直至fast指向倒数第一个元素(slow和fast始终保持k-1个移动次数)
        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        //返回val
        return slow.val;
    }

2、题二:逆置单链表

. - 力扣(LeetCode)

2.1 思路解析

此题我们使用头插法求解。

这道题的思路很简单:从第二个节点开始,每得到一个节点,将此节点进行头插操作。

注意:要将最开始的头结点的next置为null(因为链表的头节点在逆置后就变成了尾结点)

2.2 代码

public ListNode reverseList(ListNode head) {
        //当头结点head为空时
        if (head == null) {
            return head;
        }
        //获取第二个节点,将第一个节点的next置为null
        ListNode cur = head.next;
        head.next = null;
        
        //头插
        while (cur != null) {
            //先获取当前节点的下一个节点
            ListNode curN = cur.next;
            //将当前节点的next指向头结点(头插)
            cur.next = head;
            //将head更新为新头插的节点
            head = cur;
            //更新cur,继续头插
            cur = curN;
        }

        //返回逆置后的头结点
        return head;
    }

3、题三:移除链表元素(删除所有某一数值的节点,且一次循环)

. - 力扣(LeetCode)

3.1 思路解析

此题我们使用双指针法求解。

1.我们定义两个指针分别为prev(初始指向head头结点 即第一个节点)和cur(初始指向head的next节点 即第二个节点)。

2.遍历链表。

3.当cur所指节点的值为所要删除的val值时,cur向后移动,prev不动,且将prev的next指针指向移动后的cur,完成节点的删除。

4.若cur所指节点值不是所要删除的val值时,cur和prev同步后移一位。

5.当cur指向null时,遍历完成。

6.经过上述操作,除第一个节点外,其余的节点均已删除完成,我们只需额外判断第一个节点的值是否为要删除的val值即可。

3.2 代码

public ListNode removeElements(ListNode head, int val) {
        //当head为空时
        if(head == null) {
            return head;
        }

        //双指针法求解
        ListNode prev = head;
        ListNode cur = head.next;


        while (cur != null) {
            //判断当前节点的值是否为要删除的val值
            if (cur.val == val) {//若是,删除节点
                cur = cur.next;
                prev.next = cur;
            }else {//若不是,均向后移动
                cur = cur.next;
                prev = prev.next;
            }
        }
        //判断第一个节点的值是否我要删除的val值。
        if (head.val == val) {
            head = head.next;
        }
        //返回删除后的头结点
        return head;
    }

4、题四:获取链表的中间节点

. - 力扣(LeetCode)

 4.1 思路解析

此题我们使用快慢指针法求解。

1.首先,定义两个指针分别为fast和slow。

2.fast指针,每次向后移两位;slow指针,每次向后移一位。

3.链表元素个数为奇数时,当fast.next == null时,slow指向的节点就是中间节点;链表元素个数为偶数时,当fast == null时,slow指向的节点就是中间节点。

注意:

循环结束条件一定要写为:

while(fast != null && fast.next != null)

原因:

1.两者只要有一个不满足就要结束循环,说明已经找到了中间节点

2.一定要fast != null在前,避免fast.next时出现空指针异常

4.2 代码

public ListNode middleNode(ListNode head) {
        //快慢指针法求解
        ListNode slow = head;
        ListNode fast = head;
        
        //找中间节点
        //一定要fast != null在前,避免出现空指针异常
        //两个条件只要有一个不满足就结束循环,说明到了中间节点的位置
        while (fast != null && fast.next != null) {
            ListNode fastN = fast.next;
            fast = fastN.next;
            slow = slow.next;
        }

        //返回中间节点
        return slow;
    }

5、题五:分割链表

给定 x, 把一个链表整理成前半部分小于 x, 后半部分大于等于 x 的形式

链表分割_牛客题霸_牛客网

5.1 思路解析

1.将链表进行遍历

2.将val < x的节点添加到新链表head1中

3.将val >= x的节点添加到新链表head2中

4.将head1和head2进行拼接

5.返回拼接后新表的头结点head1

注意:

1.无论如何,一定要将head2的最后一个节点next域置为null

2.当表中所以元素的val值都大于等于x时,那么head1将为空表,直接返回head2即可

5.2 代码

public ListNode partition(ListNode pHead, int x) {
        //当pHead为空时
        if (pHead == null) {
            return null;
        }

        ListNode cur = pHead;
        ListNode prev = null;
        ListNode head1 = null;
        ListNode head2 = null;
        ListNode cur1 = null;
        ListNode cur2 = null;

        //遍历链表 将val < x的节点添加到新表head1中
        //将val >= x的节点添加到新表head2中
        while (cur != null) {
            if (cur.val < x) {
                if (head1 == null) {
                    head1 = cur1 = cur;
                }else {
                    cur1.next = cur;
                    cur1 = cur1.next;
                }
            }else {
                if (head2 == null) {
                    head2 = cur2 = cur;
                }else {
                    cur2.next = cur;
                    cur2 = cur2.next;
                }
            }
            cur = cur.next;
        }

        //注意:需要将head2的最后一个节点的next置为null
        if(head2 != null) {
            cur2.next = null;
        }
        //如果旧表中所有元素的val值都大于x,那么head1将会是空表,直接返回head2即可
        if (head1 == null) {
            return head2;
        }
        //将head1和head2进行拼接
        cur1.next = head2;
        return head1;
    }

 6、题六:判断链表是否回文

链表的回文结构_牛客题霸_牛客网

6.1 思路解析

回文结构,其实就是对称结构:

 

当元素个数为奇数时:

1.找到中间节点(使用上面的例题已经讲到)

2.以中间节点为头,逆置其后链表

3.逆置后,链表存在下图结构,指针从两端开始比较val值是否相等,直到相遇时结束,若均相等则为回文结构。

当元素个数为偶数时:

1.偶数时,newH和slow无法相遇

2.我们只需额外判断 当 newH.next == slow 时,说明为回文结构。

6.2 代码

public boolean chkPalindrome(ListNode A) {
        // write code here
        if (A == 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;
        ListNode curN = null;
        while (cur != null) {
            curN = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curN;
        }

        //从两端开始遍历,比较值是否相等
        ListNode newCur = A;
        while (slow != newCur) {
            if (slow.val != newCur.val) {
                return false;
            }
            if (newCur.next == slow) {
                return true;
            }
            slow = slow.next;
            newCur = newCur.next;
        }
        return true;
    }

7、题七:相交链表(找出相交节点)

. - 力扣(LeetCode)

7.1 思路解析 

首先,我们要知道,相交链表的形状为Y形,而非X形:

1.遍历求出各链表的长度,并求得长度的差值len。

2.将较长链表的头指针向后移动len个位置。

3.两个链表的头指针同时后移,会在交点处相遇。

7.2 代码

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0;
        int lenB = 0;
        //求链表1的长度
        while (curA != null) {
            lenA++;
            curA = curA.next;//curA发生改变
        }
        //求链表2的长度
        while (curB != null) {
            lenB++;
            curB = curB.next;//curB发生改变
        }
        
        //将curA和curB重新指向链表的起始位置
        curA = headA;
        curB = headB;
        
        //差值
        int len = lenA - lenB;
        
        //将较长的链表头指针后移差值个长度
        if (len < 0) {
            len = -len;
            while (len != 0) {
                curB = curB.next;
                len--;
            }
        }else {
            while (len != 0) {
                curA = curA.next;
                len--;
            }
        }
        
        //相遇处即为交点
        while (curA != curB) {
            curA = curA.next;
            curB = curB.next;
        }
        return curA;
    }

8、题八:判断链表是否带环

. - 力扣(LeetCode)

8.1 思路解析 

此题我们使用快慢指针法求解。

1.定义fast为快指针,一次移动两个位置;slow为慢指针,一次移动一个位置。

2.若链表带环,那么这两个指针必定相遇(追击问题)。

注意:

因为fast一次走两步,slow一次走一步,那进入环中后,每次移动,fast和slow之间的距离必定缩短一个节点,那么必定相遇。

(若每次移动两者间缩短的距离不为1时,那么即使有环,也可能不会相遇)

8.2 代码

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

9、题九:求环的入口点

. - 力扣(LeetCode)

9.1 思路解析

设:
起点到入口点的长度为X
相遇节点到入口点长度为Y
环的长度为C

因为fast所走路程为slow所走路程的两倍
故:
X + n*C + (C - Y) = 2*(X + C - Y)
则:
X + (2-n)*C = Y
说明:相遇节点到入口点的距离和起点到入口点的距离相等
则,从相遇节点和起点开始相向而行,相遇时的节点就是入口点

注意:我们还需要处理不是环的情况!!!

9.2 代码

public ListNode detectCycle(ListNode head) {
         //head为空时
         if (head == null) {
             return head;
         }

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

10、题十:合并两个有序链表

. - 力扣(LeetCode)

10.1 思路解析

思路很简单,就是从各链表起点开始遍历,比较val值,谁的值小,就插入到新链表当中。

若某一链表的元素全部插入新链表当中后,将另一链表剩余元素直接拼接即可

10.2 代码

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        //链表为空时
        if (list1 == null) {
            return list2;
        }
        if (list2 == null) {
            return list1;
        }

        ListNode cur1 = list1;
        ListNode cur2 = list2;
        ListNode newH = null;
        ListNode newCur = null;

        //从头遍历各链表 谁值小 谁就尾插到新链表中
        while (cur1 != null && cur2 != null) {
            if (cur1.val < cur2.val) {
                if (newH == null) {
                    newH = newCur = cur1;
                }else {
                    newCur.next = cur1;
                    newCur = newCur.next;
                }
                cur1 = cur1.next;
            }else {
                if (newH == null) {
                    newH = newCur = cur2;
                }else {
                    newCur.next = cur2;
                    newCur = newCur.next;
                }
                cur2 = cur2.next;
            }
        }

        //某一链表的元素全部插入后,将另一链表剩余元素直接拼接即可
        if (cur1 == null) {
            newCur.next = cur2;
        }
        if (cur2 == null) {
            newCur.next = cur1;
        }
        return newH;
    }

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

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

相关文章

设计模式-工厂模式的完整代码示例及测试验证

工厂模式 工厂模式 什么是工厂模式&#xff1f; 工厂模式是一种创建对象的设计模式&#xff0c;用来替代传统的 如 A anew A() 创建对象的方式&#xff0c;提供了一种 统一的接口来创建对象&#xff0c; 封装创建的过程&#xff0c;达到解耦的目的。 优缺点 优点 封装对象的创…

pytorch官网examples 实现

Getting started with transforms v2 — Torchvision 0.18 documentation (pytorch.org) 官网我导入包都报错官网代码如下&#xff1a; 不太理解所以我自己写了一段修改之后的代码&#xff0c;效果是一样的 import torch from torchvision.io import read_image import mat…

X用户最多的国家排名统计报告

数据为DataReportal发布的Twitter在各个国家的用户数统计。 2022年&#xff0c;Twitter用户最多的国家是美国&#xff0c;有7690万用户。 数据统计单位为&#xff1a;万人 数据说明&#xff1a; 数据截止时间为2022年1月 Twitter在各个国家的用户情况 2022年&#xff0c;Twit…

【TES807】 基于XCKU115 FPGA的双FMC接口万兆光纤传输信号处理平台

板卡概述 TES807是一款基于千兆或者万兆以太网传输的双FMC接口信号处理平台。该平台采用XILINX的Kintex UltraSacle系列FPGA&#xff1a;XCKU115-2FLVF1924I作为主处理器&#xff0c;FPGA外挂两组72位DDR4 SDRAM&#xff0c;用来实现超大容量数据缓存&#xff0c;DDR4的最高数据…

RIP路由协议概述

RIP【Routing Information Protocol】 RIP是为TCP/IP 环境中开发的第一个路由选择协议标准 RIP是一个【距离——矢量】路由选择协议 当路由器的更新周期为30s到来时&#xff0c;向邻居发送路由表 RIP以跳数作为唯一度量值 RIP工作原理 RIP路由协议向邻居发送整个路由表信息RI…

《昇思25天学习打卡营第1天|QuickStart》

说在前面 曾经接触过华为的910B服务级显卡&#xff0c;当时基于910B做了一些开发的工作&#xff0c;但是总感觉做的事情太低层&#xff0c;想要能自顶向下的了解下&#xff0c;因此开始了MindSpore的学习。另外也想给予提供的显卡&#xff0c;简单尝试下llm模型的训练&#xf…

2.2 类型转换与 printf 函数深度解析

1 类型转换 1.1 隐式类型转换 1.2 显式类型转换 1.3 应用&#xff1a;整除除法 2 printf 函数 2.1 语法格式 2.2 格式说明符 2.2.1 浮点数的规范性输出 2.2.2 格式说明符不匹配错误 2.3 修饰符 2.3.1 对齐方式 2.3.2 宽度 2.3.3 精度 2.3.4 填充字符 2.3.5 其他修…

【硬件调试】示波器探头一碰芯片引脚板子就短路或者闪小火花

问题: 今天拿示波器探头准备测量芯片引脚输出波形,有的引脚正常输出信号,有的会打小火花,但输出波形正常,还有一个引脚最离谱,示波器一碰,板子就立马短路,电流达到最大值,电源电压都被拉下来了,直到示波器探头拿开,板子才自动恢复,此时这个引脚测得波形如下: 根…

C++的链接指示extern “C“

目录 链接指示extern "C"A.What&#xff08;概念&#xff09;B.Why&#xff08;extern "C"的作用&#xff09;C.How &#xff08;如何使用链接指示extern "C"&#xff09; 链接指示extern “C” A.What&#xff08;概念&#xff09; extern&quo…

100 个网络基础知识普及,看完成半个网络高手!

1&#xff09;什么是链接&#xff1f; 链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。 2&#xff09;OSI 参考模型的层次是什么&#xff1f; 有 7 个 OSI 层&#xff1a;物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0…

ElasticSearch第一天

学习目标&#xff1a; 能够理解ElasticSearch的作用能够安装ElasticSearch服务能够理解ElasticSearch的相关概念能够使用Postman发送Restful请求操作ElasticSearch能够理解分词器的作用能够使用ElasticSearch集成IK分词器能够完成es集群搭建 第一章 ElasticSearch简介 1.1 什么…

javaweb个人主页设计(html+css+js)

目录 1 前言和要求 1.1 前言 1.2 设计要求 2 预览 2.1 主页页面 2.2 个人简介 2.3 个人爱好 2.4 个人成绩有代码&#xff0c;但是图片已省略&#xff0c;可以根据自己情况添加 2.5 收藏夹 3 代码实现 3.1 主页 3.2 个人简介 3.3 个人爱好 3.4 个人成绩&#xff…

shell 字符串列表操作

我的需求是这样的&#xff1a;编译多个模块的时候&#xff0c;把失败的模块添加到列表里&#xff0c;最后输出。这个列表类似这样&#xff1a;failModuleList"a b c d e" 先定义一个空的字符串列表&#xff1a; failModuleList"" 然后利用字符串的拼接方…

CVPR`24 | 又快又好!渲染速度比ENeRF快30倍!4K4D:实时4K分辨率4D视图合成

文章链接&#xff1a;https://arxiv.org/pdf/2310.11448 git链接&#xff1a; https://zju3dv.github.io/4k4d/ 本文旨在实现动态3D场景在4K分辨率下的高保真和实时视图合成。最近&#xff0c;一些动态视图合成方法在渲染质量方面表现出色。然而&#xff0c;在渲染高分辨率图像…

如何合并pdf文件?分享3种常见的方法!

在数字化办公日益普及的今天&#xff0c;PDF文件因其格式稳定、兼容性强、阅读方便等特点&#xff0c;成为了人们日常工作和学习中不可或缺的一部分。然而&#xff0c;当我们需要处理多个PDF文件时&#xff0c;如何将它们高效地合并成一个文件&#xff0c;以便更好地管理和分享…

Linux进程——进程的概念

文章目录 PCB进程排队进程标识符pid终止进程获取进程id父进程与子进程 我们在上一节内容中有简单谈到进程的感性理解&#xff0c;他在课本上的概念是&#xff0c;程序的一个执行实例或正在执行的程序 但在本质上&#xff0c;他其实就是一个被分配了系统资源&#xff08;CPU&am…

公有云API常见的认证方式

公有云API常见的认证方式 Token认证 &#xff08;百度云、腾讯云&#xff09; AK/SK认证 (阿里云、天翼云、腾讯云) RSA非对称加密方式 &#xff08;信核云灾备&#xff09; Token认证 AK/SK认证 RSA认证 种方式使用一对密钥&#xff0c;即公钥和私钥。公钥可以公开&#x…

Java数据结构-链表与LinkedList

链表 链表的概念 链表是一种物理存储结构上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序实现的。 通俗来说&#xff0c;相比较于顺序表&#xff08;物理上连续&#xff0c;逻辑上也连续&#xff09;&#xff0c;链表物理上不一定连续。 链表是…

【C++航海王:追寻罗杰的编程之路】一篇文章带你认识哈希

目录 1 -> unordered系列关联式容器 1.1 -> unordered_map 1.1.1 -> unordered_map的文档介绍 1.1.2 -> unordered_map的接口说明 1.2 -> unordered_set 2 -> 底层结构 2.1 -> 哈希概念 2.2 -> 哈希冲突 2.3 -> 哈希函数 2.4 -> 哈希冲…

Mysql进阶(一)——存储引擎

MySQL体系结构 1). 连接层 最上层是一些客户端和链接服务&#xff0c;包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于 TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程 池的概念&#xff0c;为通过认证安全接入的…