Классический вопрос для собеседования 2 со связанным списком

 Сегодня мы зададим вопрос по связанному списку, который будет связан с вопросом 141https://leetcode.cn/problems/linked-list-cycle/

 Этот вопрос просит нас проанализировать, есть ли кольцо в связанном списке. Если оно существует, оно вернет true. Если оно не существует, оно вернет false. Прежде всего, когда мы видим этот вопрос, нам нужно выправить свое мышление: как добиться желаемого эффекта? Чтобы узнать, существует ли цикл, можем ли мы увидеть, является ли следующий узел хвостового узла тем узлом, который появился раньше? Хорошенько думаем, есть ли цикл, есть ли хвостовой узел? Конечно, его не существует. Если кольцо существует, хвостового узла не будет. Если оно уже называется хвостовым узлом, оно должно быть последним узлом. Поэтому мы могли бы также изменить наше мышление и использовать быстрые и медленные двойные указатели для решения этой проблемы.

struct ListNode *fast=head;
struct ListNode *slow=head;

Мы определяем быстрое, чтобы делать два шага за раз, и медленное, чтобы делать один шаг за раз. Если есть цикл, быстрый определенно будет продвигаться по циклу и продолжать изменяться внутри. Когда медленный входит в цикл, разница в расстоянии между двумя указателей равно N, и каждый раз, когда быстрый и медленный шаг делают шаг, расстояние уменьшается на 1, всегда будет ситуация, когда расстояние равно 0. Когда быстро = медленно, существует цикл, иначе его не существует;

 

while()
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        return true;
    }
    return false;

 Но как оценить состояние этого цикла while? Когда цикл прекращается? Фаст работает быстро и останавливается, когда конец поста пуст. У некоторых могут возникнуть вопросы. Разве связанный список не имеет конца, когда есть звонок? Да, но наше мнение является условием остановки цикла. Если цикл не входит в цикл, цикла не будет, и он напрямую вернет false?

while(fast)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        return true;
    }
    return false;

Это конец? Когда мы запустим его, мы обнаружим, что он сообщает об ошибке нулевого указателя.

Где появляется нулевой указатель? Давайте подумаем о том, насколько быстро выполняются два шага за раз, fast=fast->next->next. Мы определили, что цикл остановился только тогда, когда fast==NULL, и проигнорировали ли мы момент, когда fast->next был пустой?Шерстяная ткань? Может ли fast->next в настоящее время указывать на следующий? Следовательно, этот цикл должен быть while(fast&&fast->next).

struct ListNode *fast=head;
struct ListNode *slow=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        return true;
    }
    return false;

Когда мы закончим это писать, операция пройдет.

Guess you like

Origin blog.csdn.net/weixin_67131528/article/details/134354865