zzCoze、Dify、FastGPT深度对比分析,智能体平台
2025/12/30 17:21:54
给定一个非空单链表的头结点head,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
链表节点定义:
classListNode{intval;ListNodenext;ListNode(){}ListNode(intval){this.val=val;}ListNode(intval,ListNodenext){this.val=val;this.next=next;}}示例:
输入:[1,2,3,4,5]输出:[3,4,5]解释:中间结点是值为3的结点 输入:[1,2,3,4,5,6]输出:[4,5,6]解释:有两个中间结点,值分别为3和4,返回第二个(值为4的结点)快慢指针:
核心思想:
slow(慢指针)和fast(快指针)slow每次移动 1 步,fast每次移动 2 步fast到达链表末尾时,slow正好在中间位置关键:
slow在第 (n+1)/2 个位置(真正的中间)slow在第 n/2 + 1 个位置(第二个中间结点)终止条件:
fast == null:链表长度为偶数fast.next == null:链表长度为奇数fast != null && fast.next != null/** * Definition for singly-linked list. */classListNode{intval;ListNodenext;ListNode(){}ListNode(intval){this.val=val;}ListNode(intval,ListNodenext){this.val=val;this.next=next;}}classSolution{/** * 找到链表的中间结点(如果有两个中间结点,返回第二个) * * @param head 链表头结点 * @return 中间结点 * * 算法思路(快慢指针): * 1. slow每次移动1步,fast每次移动2步 * 2. 当fast到达末尾时,slow正好在中间 * 3. 处理奇偶长度的统一逻辑 */publicListNodemiddleNode(ListNodehead){// 初始化快慢指针ListNodeslow=head;ListNodefast=head;// 快指针每次走2步,慢指针每次走1步// 当快指针到达末尾时,慢指针就在中间while(fast!=null&&fast.next!=null){slow=slow.next;// 慢指针走1步fast=fast.next.next;// 快指针走2步}returnslow;}}classSolution{/** * 两次遍历: * 1. 第一次遍历计算链表长度 * 2. 第二次遍历找到中间位置 */publicListNodemiddleNode(ListNodehead){// 第一次遍历:计算链表长度intlength=0;ListNodecurrent=head;while(current!=null){length++;current=current.next;}// 计算中间位置(第二个中间结点)intmiddle=length/2;// 第二次遍历:找到中间结点current=head;for(inti=0;i<middle;i++){current=current.next;}returncurrent;}}classSolution{/** * 使用数组存储所有结点,然后直接返回中间位置的结点 */publicListNodemiddleNode(ListNodehead){List<ListNode>nodes=newArrayList<>();ListNodecurrent=head;// 将所有结点存储到数组中while(current!=null){nodes.add(current);current=current.next;}// 返回中间结点returnnodes.get(nodes.size()/2);}}时间复杂度:
空间复杂度:
快慢指针:
初始: slow=1, fast=1 第1次循环: - slow = slow.next = 2 - fast = fast.next.next = 3 - 状态: slow=2, fast=3 第2次循环: - slow = slow.next = 3 - fast = fast.next.next = 5 - 状态: slow=3, fast=5 第3次循环检查: - fast.next = null,循环终止 返回 slow = 3快慢指针:
初始: slow=1, fast=1 第1次循环: - slow = 2, fast = 3 第2次循环: - slow = 3, fast = 5 第3次循环: - slow = 4, fast = null (5.next.next = null) 循环终止条件: fast == null 返回 slow = 4importjava.util.*;publicclassTest{// 创建链表publicstaticListNodecreateList(int[]values){if(values.length==0)returnnull;ListNodehead=newListNode(values[0]);ListNodecurrent=head;for(inti=1;i<values.length;i++){current.next=newListNode(values[i]);current=current.next;}returnhead;}// 将链表转换为数组(用于输出)publicstaticint[]listToArray(ListNodehead){List<Integer>values=newArrayList<>();ListNodecurrent=head;while(current!=null){values.add(current.val);current=current.next;}returnvalues.stream().mapToInt(i->i).toArray();}publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:奇数长度ListNodehead1=createList(newint[]{1,2,3,4,5});ListNoderesult1=solution.middleNode(head1);System.out.println("Test 1: "+Arrays.toString(listToArray(result1)));// [3,4,5]// 测试用例2:偶数长度ListNodehead2=createList(newint[]{1,2,3,4,5,6});ListNoderesult2=solution.middleNode(head2);System.out.println("Test 2: "+Arrays.toString(listToArray(result2)));// [4,5,6]// 测试用例3:单个结点ListNodehead3=createList(newint[]{1});ListNoderesult3=solution.middleNode(head3);System.out.println("Test 3: "+Arrays.toString(listToArray(result3)));// [1]// 测试用例4:两个结点ListNodehead4=createList(newint[]{1,2});ListNoderesult4=solution.middleNode(head4);System.out.println("Test 4: "+Arrays.toString(listToArray(result4)));// [2]// 测试用例5:三个结点ListNodehead5=createList(newint[]{1,2,3});ListNoderesult5=solution.middleNode(head5);System.out.println("Test 5: "+Arrays.toString(listToArray(result5)));// [2,3]// 测试用例6:四个结点ListNodehead6=createList(newint[]{1,2,3,4});ListNoderesult6=solution.middleNode(head6);System.out.println("Test 6: "+Arrays.toString(listToArray(result6)));// [3,4]// 测试用例7:大链表int[]largeArray=newint[1000];for(inti=0;i<1000;i++){largeArray[i]=i+1;}ListNodehead7=createList(largeArray);ListNoderesult7=solution.middleNode(head7);System.out.println("Test 7: "+result7.val);// 501 (1000/2 + 1 = 501)// 测试用例8:边界值ListNodehead8=createList(newint[]{100000});ListNoderesult8=solution.middleNode(head8);System.out.println("Test 8: "+Arrays.toString(listToArray(result8)));// [100000]}}快慢指针:
循环终止条件:
fast != null && fast.next != null奇偶长度统一处理:
为什么快指针要检查 fast.next != null?
fast.next.nextfast.next == null,那么fast.next.next会抛出 NullPointerException快慢指针的其他应用?