我需要一个详细的算法,在c#中有关如何在链表中找到中间元素的方法。 我检查了谷歌,所有人都在谈论在列表上并行移动的两个指针。 但实际上,我找不到算法的详细解决方案。以及如何实施这两个指针。
我需要有关性能的最佳解决方案。
答案 0 :(得分:3)
这几乎是juharr
在单链表的评论中建议你的内容。
GetMiddle
从列表的开头开始,rightPointer
看起来前面有两个元素,leftPointer
查看下一个元素(两个指针都朝同一方向移动)。最后,当没有更多要检查的元素时,leftPointer
是列表的中间节点。
在下面的代码中,Node
是一个单链接列表节点,List
只是将元素添加到列表中并公开其head
。
public T GetMiddle<T>(List<T> list)
{
Node<T> leftPointer = list.Head;
Node<T> rightPointer = list.Head;
while (rightPointer != null && rightPointer.Next != null)
{
rightPointer = rightPointer.Next.Next;
leftPointer = leftPointer.Next;
}
return leftPointer.Item;
}
public class List<T>
{
public Node<T> Head { get; private set; }
private Node<T> Last;
public void Add(T value)
{
Node<T> oldLast = Last;
Last = new Node<T>(value);
if (Head == null)
{
Head = Last;
}
else
{
oldLast.Next = Last;
}
}
}
public class Node<T>
{
public T Item { get; private set; }
public Node<T> Next { get; set; }
public Node(T item)
{
Item = item;
}
}
如果元素数量偶数,例如[1, 9]
var list = new List<int>();
foreach (var number in Enumerable.Range(1, 9))
{
list.Add(number);
}
Console.WriteLine(GetMiddle(list));
中间元素是5
。
但是,如果元素数为偶数行[1, 10]
,算法将生成6
。这是因为当right
位于9
时,它的下一个不是null
而是10
。因此,当我们完成此迭代时,right
指向null
而left
指向6
(我们将其作为中间返回)。
right: 1 -> 3 -> 5 -> 7 -> 9 -> null | end
left: 1 -> 2 -> 3 -> 4 -> 5 -> 6 | end
这意味着即使在某种情况下,你需要决定采用哪个元素作为中间 - 5或6.如果你想要5,你需要在循环中有一个额外的条件:
rightPointer = rightPointer.Next.Next;
if (rightPointer != null)
{
leftPointer = leftPointer.Next;
}
答案 1 :(得分:0)
在性能方面找到中间元素的最佳解决方案是计算它:
var mid = list[list.Length/2];
当list.Length
为偶数时,返回中间的元素。
如果你想在list.Length
为偶数时在中间返回元素,你可以减少并截断:
var mid = list[(int)((list.Length-0.5)/2)];
答案 2 :(得分:-1)
上述解决方案的Java解决方案是:
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) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
这里的节点是:
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}