持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
前言
题目来源
题目介绍
给定一个头结点为
head的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
题目分析
审查题目中的关键词,非空单链表、中间结点,所以我们应该先回想到链表的定义。
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表通常由一连串节点组成,每个节点包含该节点的数据和指向上一节点或者下一节点的引用(链接)。
用一个java对象来表示就是
* 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) {
ArrayList<ListNode> listNode=new ArrayList<ListNode>();
while (head != null) {
listNode.add(head);
head = head.next;
}
int n=listNode.size();
return listNode.get(n/2);
}
}
如上代码,先定义一个集合存储我们的节点,然后while循环我们的参数头节点,循环一个后,把next下一个又重新赋值给head,直到head不为空,说明节点已经没有下一个了。
这时候循环已经结束了,那么就取集合的中间下标的值就好了,即n/2,假如n=5,那么n就等于2,即集合的第三个值就是我们所求的结果。
官方答案验证分析
class Solution {
public ListNode middleNode(ListNode head) {
ListNode[] A = new ListNode[100];
int t = 0;
while (head != null) {
A[t++] = head;
head = head.next;
}
return A[t / 2];
}
}
官方的做法其实和我想的用集合存储是一样的,不过官方这里用了一个数组存储起来,每次遍历往里面加1,设定对应下标的值,然后取中间的值。同时还有很多其他解答方法,相对来说我觉得这种比较好理解。
class Solution {
public ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
这是另外一种做法,用两个指针 slow 与 fast 一起遍历链表。slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。这个思路也是非常的好。
总结
这道题相对来说难度稍微增加了一点,但是理解好链表的结构,还是可以做出来的。