当前位置:网站首页>【面试必看】链表的常见笔试题
【面试必看】链表的常见笔试题
2022-08-02 03:33:00 【Money、坤】
1. 合并链表
链接:https://leetcode.cn/problems/merge-two-sorted-lists
- 题目描述
给定两个有序链表,将两个升序链表合并为一个新的升序链表并返回。
- 题解
解法一:递归解法
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
//特殊情况的考虑
if(list1 ==null){
return list2; }
if(list2 ==null){
return list1; }
//此时,两个链表都不为空,开始合并
if(list1.val <= list2.val){
list1.next=mergeTwoLists(list1.next,list2);
return list1;
}else{
list2.next =mergeTwoLists(list1,list2.next);
return list2;
}
}
}
解法二:非递归解法
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 ==null){
return list2;
}
if (list2 ==null){
return list1;
}
//此时,两个链表都不为空,合并两个链表
ListNode dummyHead =new ListNode(1001); //创建一个虚拟头节点
//利用尾插进行链表的合并
ListNode tail= dummyHead;
while (list1 != null && list2 != null){
if (list1.val <= list2.val){
tail.next=list1;
tail =list1;
list1=list1.next;
}else {
tail.next =list2;
tail =list2;
list2 =list2.next;
}
}
//循环走完,表示此时已经有链表为空
if(list1 ==null){
tail.next =list2;
}
if (list2 == null){
tail.next =list1;
}
return dummyHead.next;
}
}
2. 反转链表
- 题解
/** * 反转链表 * @param head * @return */
public ListNode reverseList(ListNode head) {
//边界条件
if (head ==null || head.next ==null){
return head;
}
//定义头节点后的节点
ListNode second =head.next;
//反转第二个节点之后的所有节点
ListNode newHead =reverseList(head.next);
//改变指针引用,将sec指向head,head指向空
second.next =head;
head.next =null;
return newHead;
}
//解法二 新建一个链表,头插法
public ListNode reverseList1(ListNode head) {
if (head ==null || head.next ==null){
return head;
}
ListNode dummyHead =new ListNode(5001);
//遍历原链表,边头插法链表
while (head !=null){
ListNode node =new ListNode(head.val);
node.next =dummyHead.next;
dummyHead.next =node;
head=head.next;
}
return dummyHead.next;
}
//递归解法
public ListNode reverseList2(ListNode head) {
if (head ==null || head.next ==null){
return head;
}
ListNode sec =head.next;
//反转第二个节点之后的节点
ListNode newHead =reverseList(head.next);
//将sec指向head,head指向空
sec.next =head;
head.next =null;
return newHead;
}
3. 链表中倒数第k个节点
输入一个链表,输出该链表中倒数第k个结点。
- 题解
/** * 快慢指针的解题思路 * @param head * @param k * @return */
public ListNode FindKthToTail(ListNode head,int k) {
ListNode fast =head;
ListNode slow=head;
//先让快指针走k步
for (int i = 0; i < k; i++) {
//TODO:极端情况考虑,链表的长度小于k,走k步会发生空指针异常
if (fast ==null) {
return null;
}
fast =fast.next;
}
//接下来,让快慢指针同时走
while (fast != null){
fast =fast.next;
slow =slow.next;
}
//此时,fast为空,low走到倒数第k个节点
return slow;
}
4. 删除链表的倒数第N个节点
- 题解
class Solution {
/** * 给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 * @param head * @param n * @return */
public ListNode removeNthFromEnd(ListNode head, int n) {
//虚拟头节点的解法
ListNode dummyHead =new ListNode(-1);
dummyHead.next =head;
//快慢指针都从虚拟头节点开始向后走
ListNode fast =dummyHead;
ListNode slow =dummyHead;
//先让快指针走k+1步
for (int i = 0; i <=n ; i++) {
fast =fast.next;
}
while (fast !=null ){
fast=fast.next;
slow =slow.next;
}
//此时,slow就是待删除节点的前驱节点
//node就是待删除的节点
ListNode node =slow.next;
slow.next =node.next;
node.next =null;
return dummyHead.next;
}
}
5. 相交链表
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
 {
ListNode pA =headA;
ListNode pB =headB;
//1.相交时刚好返回交点
//2.不相交时两个同时走到null
while (pA !=pB){
pA = pA==null ?headB :pA.next;
pB = pB==null ?headA :pB.next;
}
return pA;
}
}
6. 环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
- 题解
/** * 解题思路:快慢指针 * 快指针一次走两步,慢指针一次走一步,链表若存在环,慢指针一定能追上快指针 */
public class Solution {
public boolean hasCycle(ListNode head) {
//快指针
ListNode fast = head;
//满指针
ListNode slow = head;
while (fast != null && fast.next != null) {
//一次走两步
fast = fast.next.next;
//一次走一步
slow = slow.next;
//此时,fast和low指向相同的节点,成环
if (fast == slow) {
return true;
}
}
//此时,fast==null 或fast.next ==null,直线结构
return false;
}
}
7. 回文链表
- 题解
/** * 判断单链表是否尾回文链表 * @param head * @return */
public boolean isPalindrome(ListNode head) {
//找到中间节点
ListNode middleNode =middleNode(head);
//反转中间链表及其之后的链表
ListNode r2 =reverseList(middleNode);
while (r2 != null){
if (head.val != r2.val){
return false;
}
//继续向后遍历
r2 =r2.next;
head =head.next;
}
return true;
}
/** * 查找链表的中间节点 * @param head * @return */
public ListNode middleNode(ListNode head) {
//快指针,从头开始,一次走两步
ListNode fast =head;
//慢指针,从头开始,一次走一步
ListNode low =head;
//循环终止两件 :fast为空(偶数个节点),fast.next为空(奇数个节点)
while (fast != null && fast.next !=null){
low =low.next; //走一步
fast =fast.next.next; //走两步
}
return low;
}
/** * 反转链表 * @param head * @return */
public ListNode reverseList(ListNode head) {
//边界条件
if (head ==null || head.next ==null){
return head;
}
//定义头节点后的节点
ListNode second =head.next;
//反转第二个节点之后的所有节点
ListNode newHead =reverseList(head.next);
//改变指针引用,将sec指向head,head指向空
second.next =head;
head.next =null;
return newHead;
}
8. 反转指定区间上范围的链表
- 题解
import java.util.*;
public class Main {
//链表的节点
static class Node{
int val;
Node next;
public Node(int val) {
this.val = val;
}
}
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
//链表元素的个数
int n= in.nextInt();
in.nextLine();
//链表的节点值
String nodeValue = in.nextLine();
String[] nodes =nodeValue.split(" ");
//尾插创建链表 虚拟头节点
Node dummyHead =new Node(-1);
Node tail =dummyHead;
for (int i = 0; i <n ; i++) {
Node node =new Node(Integer.parseInt(nodes[i]));
tail.next =node;
tail =node;
}
//获取区间范围
String range= in.nextLine();
//左区间
int left =Integer.parseInt(range.split(" ")[0]);
//右区间
int right =Integer.parseInt(range.split(" ")[1]);
Node newHead =reversePartList(dummyHead.next,left,right);
//进行输出处理
while (newHead !=null){
System.out.print(newHead.val+" ");
newHead =newHead.next;
}
}
//反转区间范围【left,right】的链表
private static Node reversePartList(Node head, int left, int right) {
Node dummyHead =new Node(-1);
//挂载虚拟头节点
dummyHead.next =head;
//prev 指向待反转链表的前驱节点
Node prev =dummyHead;
for (int i = 1; i <left ; i++) {
prev =prev.next;
}
//cur就是待反转链表的第一个节点
Node cur =prev.next;
for (int i = left; i <right ; i++) {
Node third =cur.next;
//将third节点先从原链表中删除再头插到cur
cur.next =third.next;
//头插
third.next =prev.next;
prev.next=third;
}
return dummyHead.next;
}
}
边栏推荐
猜你喜欢
随机推荐
Mac安装MySQL详细教程
PCB设计思路
引擎开发日志:重构骨骼动画系统
[Arduino connects the clock module to display the time on LCD1602]
【科普贴】UART接口通讯协议
开源日志库 [log4c] 使用
Modify hosts file using batch script
开源代码交叉编译操作流程及遇到的问题解决(lightdm)
如何使用 PHP 实现网页交互
GM8775C MIPI转LVDS调试资料分享
物联网方案
【TCS3200 颜色传感器与 Arduino 实现颜色识别】
阿里云华为云对比分析
为什么D类音频功放可以免输出滤波器
【科普贴】SPI接口详解
[Popular Science Post] I2C Communication Protocol Detailed Explanation - Partial Software Analysis and Logic Analyzer Example Analysis
Based on the raspberry pie smart luggage development environment set up
AD8307对数检波器
Chrome 里的小恐龙游戏是怎么做出来的?
【科普贴】I2C接口详解——偏硬件解析