Как найти средний элемент в списке ссылок без прохождения всего списка?

Как найти средний элемент в списке ссылок без прохождения всего списка.?... и в максимуме вы можете использовать только 2 указателя... как это сделать?.... а также длина списка не указана.

Ответ 1

Я не вижу, как вы могли бы это сделать без прохождения всего списка, если не знаете длину.

Я предполагаю, что ответ хочет, чтобы один указатель проходил по одному элементу за раз, а второй указатель перемещает по 2 элемента за раз. Таким образом, когда второй указатель достигнет конца, первый указатель будет посередине.

Ответ 2

Следующий код поможет вам получить средний элемент. Вам нужно использовать два указателя "быстрый" и "медленный". На каждом шаге быстрый указатель будет увеличиваться на два и медленнее будет увеличиваться на единицу. Когда список закончится, медленный указатель будет посередине.

Рассмотрим, что Node выглядит следующим образом:

class Node
{
  int data;
  Node next;
}

И LinkedList имеет метод getter для предоставления заголовка связанного списка

public Node getHead()
{
  return this.head;
}

Ниже метод получит средний элемент списка (не зная размер списка)

public int getMiddleElement(LinkedList l)
{
    return getMiddleElement(l.getHead());
}

private int getMiddleElement(Node n)
{
    Node slow = n;
    Node fast = n;

    while(fast!=null && fast.next!=null)
    {
        fast = fast.next.next;
        slow = slow.next;
    }

    return slow.data;
}

Пример:
Если список 1-2-3-4-5, средний элемент равен 3
Если в списке 1-2-3-4 средний элемент равен 3

Ответ 3

В C, используя указатели, для полноты. Обратите внимание, что это основано на алгоритме Tortoise and Hare, который используется для проверки того, содержит ли связанный список цикл.

Наш node определяется как:

typedef struct node {
    int          val;
    struct node *next;
} node_t;

Тогда наш алгоритм:

node_t *
list_middle (node_t *root)
{
    node_t *tort = root;
    node_t *hare = root;

    while (hare != NULL && hare->next != NULL) {
        tort = tort->next;
        hare = hare->next->next;
    }

    return (tort);
}

Для списка с четным числом узлов возвращается node, обрабатывающий фактический центр (например, в списке из 10 узлов, это вернет node 6).

Ответ 4

Есть два возможных ответа: один для нечетного и один для четного, оба имеют один и тот же алгоритм

Для нечетных: один указатель перемещается на один шаг, а второй указатель перемещает два элемента как время и когда второй элемент достигает последнего элемента, элемента, в котором первый указатель, средний элемент. Очень легко для странных. Попробуйте: 1 2 3 4 5

Для четного: один и тот же, один указатель перемещается на один шаг, а второй указатель перемещает два элемента как время и когда второй элемент не может перейти к следующему элементу, элементу, в котором первый указатель, средний элемент. Попробуйте: 1 2 3 4

Ответ 5

LinkedList.Node current = head;
  int length = 0;
  LinkedList.Node middle = head;

  while(current.next() != null){
      length++;
      if(length%2 ==0){
          middle = middle.next();
      }
      current = current.next();
  }

  if(length%2 == 1){
      middle = middle.next();
  }

  System.out.println("length of LinkedList: " + length);
  System.out.println("middle element of LinkedList : " + middle);

Ответ 6

Используя переменную размера, вы можете сохранить размер связанного списка.

public class LinkedList {
private Node headnode;
private int size;


public void add(int i){
    Node node = new Node(i);
    node.nextNode = headnode;

    headnode = node;
    size++;
}

public void findMiddleNode(LinkedList linkedList, int middle) {
    Node headnode = linkedList.getHeadnode();
    int count = -1;
    while (headnode!=null){
        count++;

        if(count == middle){
            System.out.println(headnode.data);
        }else {
            headnode = headnode.nextNode;
        }

    }
}


private class Node {
    private Node nextNode;
    private int data;

    public Node(int data) {
        this.data = data;
        this.nextNode = null;
    }
}

public Node getHeadnode() {
    return headnode;
}

public int getSize() {
    return size;
}
}

Затем из клиентского метода найдите середину размера списка:

public class MainLinkedList {
public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add(5);
    linkedList.add(3);
    linkedList.add(9);
    linkedList.add(4);
    linkedList.add(7);
    linkedList.add(99);
    linkedList.add(34);
    linkedList.add(798);
    linkedList.add(45);
    linkedList.add(99);
    linkedList.add(46);
    linkedList.add(22);
    linkedList.add(22);


    System.out.println(linkedList.getSize());

    int middle = linkedList.getSize()/2;

    linkedList.findMiddleNode(linkedList, middle);

}
}

Я не знаю, лучше ли это, чем два способа node, но здесь вам также не нужно проходить через весь цикл.

Ответ 7

Использование С# для поиска среднего элемента связанного списка

    static void Main(string[] args)
    {
        LinkedList<int> linked = new LinkedList<int>();
        linked.AddLast(1);
        linked.AddLast(3);
        linked.AddLast(5);
        linked.AddLast(6);
        linked.AddFirst(12);

        Console.WriteLine("Middle Element - "+ListMiddle<int>(linked));
        Console.ReadLine(); }   

public static T ListMiddle<T>(IEnumerable<T> input)
    {
        if (input == null)
            return default(T);

        var slow = input.GetEnumerator();
        var fast = input.GetEnumerator();

        while (slow.MoveNext())
        {
            if (fast.MoveNext())
            {
                if (!fast.MoveNext())
                    return slow.Current;
            }
            else
            {
                return slow.Current;
            }
        }
        return slow.Current;
    }

Ответ 8

Приведенные ниже методы Java находят середину связанного списка. Он использует два указателя: 1) медленные указатели, которые перемещаются на единицу в каждой итерации 2) быстрый указатель, который перемещается дважды в каждой итерации. Медленный указатель будет указывать на середину, когда быстрый достигает конца списка.

public SinglyLinkedListNode getMiddle(SinglyLinkedListNode list) {
        if (list == null)
            return null;
        SinglyLinkedListNode fastPtr = list.next;
        SinglyLinkedListNode slowPtr = list;
        while (fastPtr != null) {
            fastPtr = fastPtr.next;
            if (fastPtr != null) {
                slowPtr = slowPtr.next;
                fastPtr = fastPtr.next;
            }
        }

        return slowPtr;
    }

Ответ 9

Для двусвязного списка с указанными указателями на головной и хвостовой узлы
мы можем использовать как голову, так и хвост

p = head;
q = tail;
while(p != q && p->next != q)
{
    p = p->next;
    q = q->prev;
}
return p;

Введение указателя на средний узел может быть вариантом, но функции, такие как
insertNode и deleteNode должны изменить этот указатель

Ответ 10

Код Python для среднего элемента с использованием метода двух указателей:

class Node:
    def __init__(self,data):
        self.data=data
        self.next=None

class LinkedList:
    def __init__(self):
        self.head=None

    def printList(self):
        temp=self.head
        while(temp):
            print(temp.data,end=" ")
            temp=temp.next

    def insertAtBeg(self,new_data):
        new_node=Node(new_data)
        if self.head is None:
            self.head=new_node
            return

        new_node.next=self.head
        self.head=new_node

    def findMiddle(self):
        fast_ptr=self.head
        slow_ptr=self.head

        if(self.head is not None):
            while(fast_ptr is not None and fast_ptr.next is not None):
                fast_ptr=fast_ptr.next.next
                slow_ptr=slow_ptr.next
            print('Middle Element is '+ str (slow_ptr.data))

if __name__=='__main__':
    mylist=LinkedList()
    mylist.insertAtBeg(10)
    mylist.insertAtBeg(20)
    mylist.insertAtBeg(30)
    mylist.findMiddle()

Выход: средний элемент равен 20

Ответ 11

import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(10);
linkedList.add(32);
linkedList.add(90);
linkedList.add(43);
linkedList.add(70);
linkedList.add(20);
linkedList.add(45);

int middle = linkedList.size()/2;
System.out.println(linkedList.get(middle));

}}

Ответ 12

Я добавляю свое решение, которое будет работать как для нечетного, так и для четного числа элементов, таких как

1-2-3-4-5 средний элемент 3

1-2-3-4 средний элемент 2,3

Он основан на том же принципе быстрого указателя и принципа медленного указателя, как упомянуто в некоторых других ответах в посте.

public class linkedlist{

Node head;

static class Node{
    int data;
    Node next;
    Node(int d)  { data = d;  next=null; } 
}
public static void main(String args[]){
    linkedlist ll = new linkedlist();       
    Node one = new Node(1);
    Node second = new Node(2);
    Node third = new Node(3);
    Node fourth = new Node(4);
    Node five = new Node(5);
    Node sixth = new Node(6);
    Node seventh = new Node(7);
    Node eight = new Node(8);
    ll.head = one;
    one.next = second;
    second.next = third;
    third.next = fourth;
    fourth.next = five;
    five.next = sixth;
    sixth.next = seventh;
    seventh.next = eight;
    ll.printList();
    ll.middleElement();
}
public void printList(){
    Node n = head;
    while( n != null){
        System.out.print(n.data+ "  ---> ");
        n = n.next;
    }
}

public void middleElement(){
    Node headPointer = head;
    Node headFasterPointer = head;
    int counter = 0;

    if(head != null){
    while(headFasterPointer.next != null ){

        if(headFasterPointer.next.next != null){
        headFasterPointer = headFasterPointer.next.next;
        headPointer = headPointer.next;
        } 
        else
         {
        headFasterPointer = headFasterPointer.next;
        } 
        counter++;
    }

    System.out.println();
    System.out.println("The value of counter is "+ counter);
    if(counter %2 == 0){
     System.out.println("The middle element is " + headPointer.data +","+ headPointer.next.data);
    } else 
    {
     System.out.println("The middle element is " + headPointer.data );
    }



    }

}}

Ответ 13

Глупо использовать два указателя "быстрый" и "медленный". При этом оператор следующий используется в 1,5 раза. Оптимизация отсутствует.

Использование указателя для сохранения среднего элемента может помочь вам.

list* find_mid_1(list* ptr)
{
    list *p_s1 = ptr, *p_s2 = ptr;
    while (p_s2=p_s2->get_next())
    {
        p_s2 = p_s2->get_next();
        if (!p_s2)
            break;
        p_s1 = p_s1->get_next(); 
    }
    return p_s1;
}