忙处事为,常向闲中先检点,过举自稀。
动时念想,预从静里密操持,非心自息
PS: 如果有两个中间结点,则返回第二个中间结点。如[1,2,3,4] 返回 3
class Solution {
public ListNode middleNode(ListNode head) {
if(head == null || head.next == null) return head;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
上面的代码是876. 链表的中间结点 的模版答案。
但是今天刷到148. 排序链表时,首先想到的就是采用归并排序。As we all know, 归并排序的第一个步骤就是分解(将待排序列分为两个部分)。
归并排序的三个步骤:
- 分解
- 排序:只有这一步会涉及到递归操作(每次都要再分解)。
- 合并
链表分解:那不得先拿到中间节点吗? 于是我一顿骚操作… 嘴角微微上扬
However, it’s not that simple.
尴尬了,居然出错了… (PS: StackOverflowError(栈溢出) 的问题一般都跟递归脱不了干系)
什么原因呢?
其实就是在每次递归的过程中,都要对子序列再进行分解。而上面的代码在有两个中间节点时,取得是后一个。这就会在只有两个元素时,产生无限循环,直至StackOverflowError.
当序列为[2,3]时,求中间节点得到的是[3].此时左半部分( head- mid)还是原来的[2,3], 右半部分为null。
如何解决该问题:
就是求中间节点时,遇到两个中间节点时,取第一个即可。
class Solution {
public ListNode middleNode(ListNode head) {
if(head == null || head.next == null) return head;
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}