Поиск среднего элемента LinkedList в Java — алгоритм двух указателей

Чтобы понять этот пример, сначала ознакомьтесь со следующими темами:

  • Класс LinkedList в Java

  • Структура данных LinkedList

Пример 1: Получение среднего элемента LinkedList за один проход

class LinkedList {

  // создаём объект класса Node
  // представляет голову связанного списка
  Node head;

  // статический вложенный класс
  static class Node {
    int value;

    // соединяем каждый узел со следующим
    Node next;

    Node(int d) {
      value = d;
      next = null;
    }
  }

  public static void main(String[] args) {

    // создаём объект LinkedList
    LinkedList linkedList = new LinkedList();

    // присваиваем значения каждому узлу связанного списка
    linkedList.head = new Node(1);
    Node second = new Node(2);
    Node third = new Node(3);

    // соединяем каждый узел связанного списка со следующим
    linkedList.head.next = second;
    second.next = third;

    // печатаем связанный список
    Node pointer = linkedList.head;
    System.out.print("LinkedList: " );
    while (pointer != null) {
      System.out.print(pointer.value + " ");
      pointer = pointer.next;
    }

    // Находим средний элемент
    Node ptr1 = linkedList.head;
    Node ptr2 = linkedList.head;

    while (ptr1.next != null) {

      // увеличиваем ptr1 на 2, а ptr2 на 1
      // если ptr1 указывает на последний элемент
      // ptr2 будет указывать на средний элемент
      ptr1 = ptr1.next;
      if(ptr1.next !=null) {
        ptr1 = ptr1.next;
        ptr2 = ptr2.next;
      }
    }

    System.out.println("\nMiddle Element: " + ptr2.value);

  }
}

Вывод:

LinkedList: 1 2 3
Middle Element: 2

В примере выше мы реализовали структуру данных связанный список в Java. Затем мы находим средний элемент связанного списка за один цикл. Обратите внимание на код:

while (ptr1.next != null) {

  // увеличиваем ptr1 на 2, а ptr2 на 1
  // если ptr1 указывает на последний элемент
  // ptr2 будет указывать на средний элемент
  ptr1 = ptr1.next;
  if(ptr1.next !=null) {
    ptr1 = ptr1.next;
    ptr2 = ptr2.next;
  }
}

Здесь у нас есть две переменные ptr1 и ptr2. Мы используем эти переменные, чтобы пройти по связанному списку.

На каждой итерации ptr1 будет обращаться к двум узлам, а ptr2 — к одному узлу связанного списка.

Теперь, когда ptr1 достигнет конца связанного списка, ptr2 будет в середине. Таким образом, мы можем получить середину связанного списка за одну итерацию.

Пример 2: Получение среднего элемента LinkedList с помощью класса LinkedList

import java.util.LinkedList;

class Main {
  public static void main(String[] args){

    // создаём связанный список с помощью класса LinkedList
    LinkedList<String> animals = new LinkedList<>();

    // добавляем элементы в LinkedList
    animals.add("Dog");
    animals.addFirst("Cat");
    animals.addLast("Horse");
    System.out.println("LinkedList: " + animals);

    // получаем средний элемент
    String middle = animals.get(animals.size()/2);
    System.out.println("Middle Element: " + middle);
    }
}

Вывод:

LinkedList: [Cat, Dog, Horse]
Middle Element: Dog

В примере выше мы использовали класс LinkedList, чтобы реализовать структуру данных связанный список. Обратите внимание на выражение:

animals.get(animals.size()/2)
  • size()/2 — возвращает позицию среднего элемента

  • get() — возвращает элемент в средней позиции