如何在链表中找到中间元素

时间:2017-10-27 13:36:04

标签: c# .net oop data-structures

我需要一个详细的算法,在c#中有关如何在链表中找到中间元素的方法。 我检查了谷歌,所有人都在谈论在列表上并行移动的两个指针。 但实际上,我找不到算法的详细解决方案。以及如何实施这两个指针。

我需要有关性能的最佳解决方案。

3 个答案:

答案 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指向nullleft指向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; }
}