关于链表的中间节点问题的坑

忙处事为,常向闲中先检点,过举自稀。
动时念想,预从静里密操持,非心自息


876. 链表的中间结点

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, 归并排序的第一个步骤就是分解(将待排序列分为两个部分)。

归并排序
归并排序的三个步骤:

  1. 分解
  2. 排序:只有这一步会涉及到递归操作(每次都要再分解)。
  3. 合并

链表分解:那不得先拿到中间节点吗? 于是我一顿骚操作… 嘴角微微上扬

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

猜你喜欢

转载自blog.csdn.net/wangcheeng/article/details/117770446