You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单链表找中间节点:我的Java解法为何对奇数长度链表失效?

单链表找中间节点Java解法失效原因分析

正在解决LeetCode上的单链表找中间节点问题,已知基于列表的解法,但自己的Java代码对奇数长度链表无效,请求分析原因。

ListNode类定义

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

我的源代码

public class middle_linked_list {

    public static void main(String args[]){
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);

        System.out.println(middleElement(head).val);
    }

    public static ListNode middleElement(ListNode head){

        int size = 0;
        float counter = 0;
        float middle = 0;

        ListNode mid = head;

        while(head != null)
        {
            ++size;
            head = head.next;
        }

        if(size % 2 == 0){
            middle = size/2f;

        }else{
            middle = Math.round(size/2f);
        }
        
       
        while(mid != null){

            if(counter == middle)
            {
                System.out.println(mid.val);
                return mid;
                
            }

            System.out.println(mid.val);
            ++counter;
            mid = mid.next;

        }


        return null;
    }
}

我的解题思路

  • 遍历链表获取其长度;
  • 定义float类型变量middle;
  • 若链表长度为奇数则向上取整,偶数则直接取半;
  • 当计数器等于middle时返回对应节点。

问题现象

代码对[1,2,3,4]、[1,2,3,4,5,6]等偶数长度链表有效,但对[1,2,3,4,5,6,7]这类奇数长度链表无效。


失效原因分析

1. 奇数长度时middle值计算错误

LeetCode对单链表中间节点的要求是:

  • 奇数长度时返回正中间节点(如长度7时返回第4个节点,对应0-based索引3);
  • 偶数长度时返回第二个中间节点(如长度4时返回第3个节点,对应0-based索引2)。

你的代码中,奇数长度时用Math.round(size/2f)计算middle:

  • 长度5时,size/2f=2.5,Math.round(2.5)返回3(Java中round方法对.5的取值规则是取最近的偶数);
  • 长度7时,size/2f=3.5,Math.round(3.5)返回4。

这导致middle值比正确的0-based索引大1,最终返回的节点偏后。

2. 计数器判断时机与middle值不匹配

你的循环逻辑是先判断counter是否等于middle,再递增counter并移动节点:

  • 初始counter=0对应head节点(0-based索引0);
  • 每次判断后,counter才会+1,mid才会移动到下一个节点。

当middle值被错误计算为3(长度5时),循环会在counter=3时返回mid,此时mid已经移动到了索引3的节点(值4),而正确的中间节点是索引2的节点(值3)。


修正方案

不需要使用float类型,直接用整数除法即可满足需求:

public static ListNode middleElement(ListNode head){
    int size = 0;
    int counter = 0;
    int middle = 0;

    ListNode mid = head;
    ListNode temp = head;

    // 遍历获取长度
    while(temp != null)
    {
        ++size;
        temp = temp.next;
    }

    // 整数除法直接适配奇偶情况
    middle = size / 2;

    while(mid != null){
        if(counter == middle)
        {
            return mid;
        }
        ++counter;
        mid = mid.next;
    }

    return null;
}

说明:

  • 整数除法size/2:长度5时得到2,长度7时得到3,正好对应正确的0-based索引;
  • 保持原有判断逻辑,counter等于middle时返回当前mid,正好是目标节点。

另外可以用快慢指针法优化,仅需一次遍历即可找到中间节点,避免两次遍历的开销:

public static ListNode middleElement(ListNode head) {
    ListNode slow = head;
    ListNode fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

内容的提问来源于stack exchange,提问作者Khandkar Islam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:40:18