найти средний элемент связанного списка

User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

найти средний элемент связанного списка

Post by rzen »

задали приятелю вопрос на интервью, ответ (от интервьюера) был такой, мол запустить цикл в цикле, внешний цикл по каждому элементу, внутренний через один, когда внутренний закончится, внешний как раз укажет на средний элемент.

а как бы вы такую задачу решили практически?

да, чуть не забыл, язык жаба.
Don't code today what you can't debug tomorrow.
User avatar
valchkou
Уже с Приветом
Posts: 4185
Joined: 27 Apr 2011 03:43
Location: Сергели ->Chicago

Re: найти средний элемент связанного списка

Post by valchkou »

rzen wrote: а как бы вы такую задачу решили практически?
да, чуть не забыл, язык жаба.
если я правильно понял задачу то можно так

Code: Select all

	
     List<String> list = new LinkedList();
     list.add("firs");
     list.add("middle");
     list.add("last");
	
     // поиск среднего элемента	
     int idx = list.size()/2;
     String s = list.get(idx);
     System.out.println(s); -> middle
Last edited by valchkou on 13 Mar 2013 17:19, edited 1 time in total.
User avatar
Flash-04
Уже с Приветом
Posts: 63377
Joined: 03 Nov 2004 05:31
Location: RU -> Toronto, ON

Re: найти средний элемент связанного списка

Post by Flash-04 »

давайте вначале определим что есть "средний элемент" для списка из чётного кол-ва элементов? ну например список из двух элементов :)
Not everyone believes what I believe but my beliefs do not require them to.
User avatar
fruit6
Уже с Приветом
Posts: 4205
Joined: 10 Jan 2004 01:22
Location: n-sk -> MD -> VA

Re: найти средний элемент связанного списка

Post by fruit6 »

один цикл.
хранить ссылку на элемент списка и менять ее на element.nextElement() на каждый четный проход в цикле.
начальное значение ссылки - первый элемент списка.
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

да, это был первый же предложенный вариант на что интервьющица сообщила что у связанного списка нет метода size() не знаю было ли это её заблуждение или дополнительная вводная на засыпку но такое решение небыло принято
Don't code today what you can't debug tomorrow.
User avatar
fruit6
Уже с Приветом
Posts: 4205
Joined: 10 Jan 2004 01:22
Location: n-sk -> MD -> VA

Re: найти средний элемент связанного списка

Post by fruit6 »

valchkou wrote:
rzen wrote: а как бы вы такую задачу решили практически?
да, чуть не забыл, язык жаба.
если я правильно понял задачу то можно так

Code: Select all

	
     List<String> list = new LinkedList();
     list.add("firs");
     list.add("middle");
     list.add("last");
	
     // поиск среднего элемента	
     int idx = list.size()/2;
     String s = list.get(idx);
     System.out.println(s); -> middle
подразумевается что get() & size() недоступны. только ссылка на первый элемент.
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

fruit6 wrote:один цикл.
хранить ссылку на элемент списка и менять ее на element.nextElement() на каждый четный проход в цикле.
начальное значение ссылки - первый элемент списка.
не вижу как можно обойти полный проход по всем элементам полтора раза.
Don't code today what you can't debug tomorrow.
avitya
Уже с Приветом
Posts: 3836
Joined: 13 Sep 2007 10:06

Re: найти средний элемент связанного списка

Post by avitya »

В первом посте написан квадратичный алгоритм (цикл в цикле), в то время, как от вас требуется иметь два итератора, один двигать на два элемента, другой на один. Так как это связанный список, то у него метода get(idх) нету. Кроме того, большинство реализаций для связанного списка оптимизируют функцию splice(), в результате которой size() становится линейным (есть и обратные, где size() O(1), а splice() линейная).
Итого, итератор посещает, как правильно заметили, 1.5N элементов, что все ещё О(Н)...
User avatar
valchkou
Уже с Приветом
Posts: 4185
Joined: 27 Apr 2011 03:43
Location: Сергели ->Chicago

Re: найти средний элемент связанного списка

Post by valchkou »

rzen wrote:да, это был первый же предложенный вариант на что интервьющица сообщила что у связанного списка нет метода size() не знаю было ли это её заблуждение или дополнительная вводная на засыпку но такое решение небыло принято
Если она имела ввиду, что "a давайте предположим, что нет метода size()",
тогда сразу встает вопрос, а может это и не жава вовсе, может я вам тогда по русски напишу
- беру значит список, отмеряю на глаз половину и уякс топором
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

мне интересно не окажется ли в практическом смысле проще сконвертировать список в коллекцию и уже искать серединный элемент в ней? на конвертацию потратится один проход, соберутся ссылки, будут потери на пере-аллокацию памяти для коллекции в процессе наполнения, потеря памяти на ссылки на объекты и собссно всё, какие ещё потери?
Don't code today what you can't debug tomorrow.
User avatar
fruit6
Уже с Приветом
Posts: 4205
Joined: 10 Jan 2004 01:22
Location: n-sk -> MD -> VA

Re: найти средний элемент связанного списка

Post by fruit6 »

Code: Select all


public class LinkedListNode {
	
	private LinkedListNode nextElement;
	private int id; // for demo purpose
	
	public LinkedListNode(LinkedListNode next, int id) {
		this.nextElement = next;
		this.id = id;
	}
	
	public LinkedListNode nextElement() {
		return nextElement;
	}
	
	public static void main(String[] args) {
		LinkedListNode node7 = new LinkedListNode(null, 7);
		LinkedListNode node6 = new LinkedListNode(node7, 6);
		LinkedListNode node5 = new LinkedListNode(node6, 5);
		LinkedListNode node4 = new LinkedListNode(node5, 4);
		LinkedListNode node3 = new LinkedListNode(node4, 3);
		LinkedListNode node2 = new LinkedListNode(node3, 2);
		LinkedListNode node1 = new LinkedListNode(node2, 1);
		
		// List: node1 -> node2 -> node3 -> node4 -> node5 
		LinkedListNode middle = findMiddleElement(node1);
		System.out.println("middle element id: " + middle.id);
	}
	
	/**
	 * 
	 * @param firstElement not null ref to first node.
	 * @return
	 */
	public static LinkedListNode findMiddleElement(LinkedListNode firstElement) {
		LinkedListNode middle = firstElement;
		LinkedListNode currentNode = firstElement;
		boolean even = true;
		while (currentNode.nextElement() != null) {
			currentNode = currentNode.nextElement();
			if (even)
				even = false;
			else {
				even = true;
				middle = middle.nextElement();
			}
		}
		
		return middle;
	}
}

avitya
Уже с Приветом
Posts: 3836
Joined: 13 Sep 2007 10:06

Re: найти средний элемент связанного списка

Post by avitya »

С этим решением несколько проблем.
1. Это потеря памяти
2. Чтоб скопировать список, уже Н операций надо сделать
3. Новую коллекцию надо удалить
4. Нужно изворачиваться, скажем новая коллекция должна быть скорее всего коллекцией итераторов (то есть собрать придется Н+1 объект как минимум).
В реальности, конечно, если такое надо делать, то не нужно список использовать, но задача на то и задача :)
User avatar
valchkou
Уже с Приветом
Posts: 4185
Joined: 27 Apr 2011 03:43
Location: Сергели ->Chicago

Re: найти средний элемент связанного списка

Post by valchkou »

avitya wrote:Так как это связанный список, то у него метода get(idх) нету.
А на яве есть, хотя он и линейный но есть, зачем велосипед придумывать ? это ж ява
avitya
Уже с Приветом
Posts: 3836
Joined: 13 Sep 2007 10:06

Re: найти средний элемент связанного списка

Post by avitya »

:) вы упускаете смысл слова задача :)
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

avitya wrote:С этим решением несколько проблем.
1. Это потеря памяти
2. Чтоб скопировать список, уже Н операций надо сделать
3. Новую коллекцию надо удалить
4. Нужно изворачиваться, скажем новая коллекция должна быть скорее всего коллекцией итераторов (то есть собрать придется Н+1 объект как минимум).
В реальности, конечно, если такое надо делать, то не нужно список использовать, но задача на то и задача :)
потеря памяти да, но и не придется полтора раза проходить все элементы списка.

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

что касается того что не надо использовать список это факт, но да, на то она и задача :)
Don't code today what you can't debug tomorrow.
User avatar
SVK
Уже с Приветом
Posts: 8241
Joined: 23 Jul 2003 03:53
Location: SPb - KW - NY - CT - MD

Re: найти средний элемент связанного списка

Post by SVK »

rzen wrote:потеря памяти да, но и не придется полтора раза проходить все элементы списка.
Если список обозримого размера, то полтора прохода по нему - это ерунда, о которой не стоит переживать.
А вот если список действительно гигантский, то скорее уж его промежуточная конвертация во что угодно выльется в катастрофу от потери памяти. И я сильно сомневаюсь, что конвертация N элементов списка пройдет быстрее, чем 1.5*N простых прохода по next()
LG - Life's good.
But good life is much better.
User avatar
АццкоМото
Уже с Приветом
Posts: 15242
Joined: 01 Mar 2007 05:18
Location: VVO->ORD->DFW->SFO->DFW->PDX

Re: найти средний элемент связанного списка

Post by АццкоМото »

Да просто же. Точно также, как ищутся петли в связанном списке: начинается траверсал с начала двумя указателями, один передвигается на один элемент вперед, второй - на два. как второй уперся в конец, первый - в середине
Мат на форуме запрещен, блдж!
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

SVK wrote:
rzen wrote:потеря памяти да, но и не придется полтора раза проходить все элементы списка.
Если список обозримого размера, то полтора прохода по нему - это ерунда, о которой не стоит переживать.
А вот если список действительно гигантский, то скорее уж его промежуточная конвертация во что угодно выльется в катастрофу от потери памяти. И я сильно сомневаюсь, что конвертация N элементов списка пройдет быстрее, чем 1.5*N простых прохода по next()
"конвертация" это тривиальная манипуляция ссылками, с чего бы ей стать катастрофой?
Don't code today what you can't debug tomorrow.
avitya
Уже с Приветом
Posts: 3836
Joined: 13 Sep 2007 10:06

Re: найти средний элемент связанного списка

Post by avitya »

В основном, что надо выделить массив размера Н * размер элемента. Если у вас миллиард элементов....
User avatar
АццкоМото
Уже с Приветом
Posts: 15242
Joined: 01 Mar 2007 05:18
Location: VVO->ORD->DFW->SFO->DFW->PDX

Re: найти средний элемент связанного списка

Post by АццкоМото »

Короче...

Code: Select all

struct node* findMiddle(struct node* head)
{
  struct node *slow_ptr = head;
  struct node *fast_ptr = head;
 
  if(head!=NULL) {
       while((fast_ptr->next)!=NULL &&
               (fast_ptr->next->next)!=NULL) {
          fast_ptr = fast_ptr->next->next;
          slow_ptr = slow_ptr->next;
       }
       return slow_ptr;
  } else {
    return NULL;
  }
}
Мат на форуме запрещен, блдж!
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

avitya wrote:В основном, что надо выделить массив размера Н * размер элемента. Если у вас миллиард элементов....
В коллекции хранятся ссылки на элементы, не сами элементы.
Don't code today what you can't debug tomorrow.
Reds
Уже с Приветом
Posts: 155
Joined: 28 Apr 2011 14:28
Location: MD->CA->WA

Re: найти средний элемент связанного списка

Post by Reds »

Java:

Code: Select all

public class FindMiddleElementOfLinkedList {

	public Node<Integer> findMiddleElementOfLinkedList(Node<Integer> head) {
		if (head == null) {
			throw new IllegalArgumentException("head is null");
		}

		Node<Integer> result = head;
		Node<Integer> doubleJumpNode = head;
		while (doubleJumpNode.next != null && doubleJumpNode.next.next != null) {
			doubleJumpNode = doubleJumpNode.next.next;
			result = result.next;
		}

		return result;

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Node<Integer> head = new Node<Integer>(1);

		Node<Integer> node2 = new Node<Integer>(2);
		head.next = node2;

		Node<Integer> node3 = new Node<Integer>(3);
		node2.next = node3;

		Node<Integer> node4 = new Node<Integer>(4);
		node3.next = node4;

		Node<Integer> node5 = new Node<Integer>(5);
		node4.next = node5;

		Node<Integer> node6 = new Node<Integer>(6);
		node5.next = node6;

		Node<Integer> node7 = new Node<Integer>(7);
		node6.next = node7;

		Node<Integer> node8 = new Node<Integer>(8);
		node7.next = node8;

		Node<Integer> node9 = new Node<Integer>(9);
		node8.next = node9;

		FindMiddleElementOfLinkedList service = new FindMiddleElementOfLinkedList();
		Node<Integer> middleOne = service.findMiddleElementOfLinkedList(head);
		
	    System.out.println(middleOne.value);
		

	}

	private static class Node<T> {
		public T value;
		public Node<T> next;

		public Node(T value) {
			super();
			this.value = value;
		}

	}

}
avitya
Уже с Приветом
Posts: 3836
Joined: 13 Sep 2007 10:06

Re: найти средний элемент связанного списка

Post by avitya »

rzen wrote:
avitya wrote:В основном, что надо выделить массив размера Н * размер элемента. Если у вас миллиард элементов....
В коллекции хранятся ссылки на элементы, не сами элементы.
Я понимаю, но ссылка это тоже память. В простейшем случае указатель -- 4 байта (в 32битнойсистеме). И вот вы затребовали 4 гигабайта последовательной памяти :)
User avatar
rzen
Уже с Приветом
Posts: 24375
Joined: 18 Nov 2003 16:42

Re: найти средний элемент связанного списка

Post by rzen »

avitya wrote:
rzen wrote:
avitya wrote:В основном, что надо выделить массив размера Н * размер элемента. Если у вас миллиард элементов....
В коллекции хранятся ссылки на элементы, не сами элементы.
Я понимаю, но ссылка это тоже память. В простейшем случае указатель -- 4 байта (в 32битнойсистеме). И вот вы затребовали 4 гигабайта последовательной памяти :)
как минимум такое количество памяти (and then some) уже размещено на список. времена последовательного доступа (и сортировки на магнитной ленте) давно прошли, слава всевышнему.
Don't code today what you can't debug tomorrow.
avitya
Уже с Приветом
Posts: 3836
Joined: 13 Sep 2007 10:06

Re: найти средний элемент связанного списка

Post by avitya »

Ну разница в том, что для списка не нужна последовательная память (одно из редких преимуществ списка). Во вторых, если у вас всего 4 (32 битная система), то как бы всё... Если со всякими ПАЕ и т.д. -- то всё равно 4г выделить последовательно это время и т.д. Выделите на своей машине массив из милларда элементов. :)

Return to “Работа и Карьера в IT”