文章目录
- 引言
- 反转单链表
- 题目描述
- 示例:
- 题解思路
- 代码实现:
- 移除链表元素
- 题目描述:
- 示例
- 思路解析:
- 链表的中间结点
- 题目描述:
- 示例:
- 思路解析
- 代码实现如下:
- 链表中倒数第k个结点
- 题目描述
- 示例
- 思路解析:
- 代码实现如下:
- 总结
引言
单链表的操作算法是笔试面试中较为常见的题目。
本文将着重介绍平时面试中常见的关于链表的应用题目,马上要进行秋招了。希望对你们有帮助 _😀
反转单链表
题目描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0≤n≤1000
要求:空间复杂度 O(1) ,时间复杂度 O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
示例:
题解思路
(1)定义两个指针: pser 和 sur ;sur 在前 pser 在后。
(2)sur用于遍历,pser用于交换位置,并插入到头节点前面
(3)将head里面的next置为null
(4)每一次插入顺序为将sur的位置付给pser,然后sur向前走一步,令pser里的next设为head;这时候pser为头节点,我们再将pser赋给head作为新的头节点。每循环一次头节点向前走一步
(5)循环上述过程,直至 sur 到达链表尾部
代码实现:
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* public ListNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
public ListNode ReverseList (ListNode head) {
// write code here
if (head == null || head.next == null) {
return head;
}
ListNode sur = head.next;
ListNode pser = head;
head.next = null;
while (sur != null) {
pser = sur;
sur = sur.next;
pser.next = head;
head = pser;
}
return head;
}
}
移除链表元素
题目描述:
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
示例
思路解析:
我们依旧需要对该单链表进行判断,如果为空,就直接返回
由于我们需要删除很多个这样的节点,但是我们的单链表却是单向的,按照上面的写法,我们则需要遍历很多次单链表,大大的增加了复杂度,我们为了降低时间复杂度,使它降为O(N);
我们设两个遍历节点,进行遍历,一个在前为cur,一个在后prev
前面的cur负责进行遍历删除,后面的prev负责跟在cur后面记录cur的上一节点
当cur下一节点不是我们所要删除的元素时,这时候我们将prev变为我们当前节点的cur,而cur变为当前节点的next
当前的删除方法只能删除第一个节点以后的元素,所以我们还需要处理第一个元素是我们所需要删除的情况。
代码实现如下
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null) {
return null;
}
ListNode prev = head;
ListNode cur = head.next;
while (cur != null) {
if(cur.val == val) {
prev.next = cur.next;
cur = cur.next;
}else {
prev = cur;
cur = cur.next;
}
}
if(head.val == val) {
head = head.next;
}
return head;
}
}
链表的中间结点
题目描述:
给你单链表的头结点 head ,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例:
思路解析
我们依旧两个定义两个指针,一个一次性走两步,一个一次性走一步
当快的指针到达终点时,慢的指针所☞指位置就是我们所需要的中间位置
就像大人与小孩子一起走路,大人的速度是小孩子的两倍
大人到达终点时,小孩子才走到一半!
代码实现如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
//1、找中间节点
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
注意:fast != null与fast.next != null不可以调换
链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
示例
输入:
1,{1,2,3,4,5}
返回值:
{5}
思路解析:
依旧是两个指针,分别为fast和slow,fast先出发,fast出发k-1步后,slow出发,中间保持k-1个节点的距离,fast所指向下一节点为null时结束
代码实现如下:
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head, int k) {
if (k <= 0 || head == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
//1. fast走k-1步
while (k - 1 != 0) {
fast = fast.next;
if (fast == null) {
return null;
}
k--;
}
//2、3、
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
总结
关于《【数据结构】 单链表面试题讲解》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!