Рубрики
Без рубрики

Найдите длину петли в связанном списке

Решение для поиска длины цикла в связанном списке. Полезно для кодирования интервью и другого решения головоломки. Tagged с помощью компьютерной науки, JavaScript, новичков.

Я занимаюсь катами, чтобы улучшить свои навыки кодирования. Я сейчас в 6Kyu на Надеды . На этой неделе моя интересная проблема была:

Вам дают узел, который является началом связанного списка. Этот список всегда содержит хвост и петлю. Ваша цель – определить длину петли. Цикл выглядит так:

Как решить

Есть 2 части этого вопроса:

  1. Выяснить, когда вы находитесь в петле
  2. Считать узлы в петле

Фигура Когда ты в петле

После быстрого Google я обнаружил алгоритм обнаружения цикла Флойда, который, как говорится, обнаруживает, застряли ли вы в цикле. Вы также можете использовать его, чтобы найти именно то, где находится начало цикла, но это не связано с объемом этого вопроса.

Основная идея заключается в том, что у вас есть 2 указателя:

  • Один перемещается к следующему узлу на 1 (медленный указатель)
  • Второй указатель, который перемещается по 2 узлам (быстрый указатель)

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

Поэтому код выглядит следующим образом:

function getNodeInLoop(node){
   let slow = node;
   let fast = node.next;

//problem assumes there is always going to be a loop
//so no need to check
   while(slow !== fast){ 
        slow = slow.next; //move by 1
        fast = fast.next.next; //move by 2
    }

  return slow; 
}

Поэтому мы возвращаем Известное место узла в петле.

Считать

Мы можем начать считать узлы! Мы принимаем наш узел, в котором как медленные, так и быстрые указатели соответствовали (здесь Seennode) как рассматривать его как корневой узел в цикле. Мы используем переменную «указателя», чтобы отслеживать там, что мы находимся в нашей петле и «счете», чтобы подсчитать количество узлов, через которые мы прошли:

    let size = 1
    let seenNode = getNodeInLoop(node); 
    let pointer = seenNode.next; 

    while(pointer !== seenNode ){
        size++; 
        pointer = pointer.next;
    }

    return size;

Решение

Полное решение заключается в следующем:

function loop_size(node){
    let size = 1;
    let seenNode = getNodeInLoop(node); 
    let pointer = seenNode.next; 

    while(pointer !== seenNode ){
        size++; 
        pointer = pointer.next;
    }

    return size;
}

function getNodeInLoop(node){
   let slow = node;
   let fast = node.next;

//problem assumes there is always going to be a loop
//so no need to check
   while(slow !== fast){ 
        slow = slow.next; //move by 1
        fast = fast.next.next; //move by 2
    }

  return slow; 
}

Та-да!

Ссылки

Вопрос о кодексах Алгоритм обнаружения цикла Флойда – явное объяснение на Hackerrank

P.S Я не уверен, почему, но Codewars не нравятся отдельные функции для решения, и, следовательно, большинство моих решений для кодирования просто написаны как одна функция. P.P.S Как всегда, это только мое решение, и я знаю, что есть другие реализации. Не стесняйтесь комментировать, чтобы начать обсуждение:)!

Оригинал: “https://dev.to/lost_semicolon/find-the-length-of-a-loop-in-a-linked-list-46i8”