Хобрук: Ваш путь к мастерству в программировании

ошибка для списка размера 2 в отсортированном списке слияния K

Я решаю проблему на InterviewBit (ссылка): https://www.interviewbit.com/problems/merge-k-sorted-lists/ Мне нужно объединить k отсортированных связанных списков и вернуть их как один отсортированный список. Это мое решение:

 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
bool is(const ListNode& x, const ListNode& y) { return x.val < y.val; }
ListNode* Solution::mergeKLists(vector<ListNode*> &A) {
    vector<ListNode> m;
    for(int i=0;i<A.size();i++){
        while(A[i]!=NULL){
            m.push_back(*A[i]);
            A[i]=A[i]->next;
        }
    }
    sort(m.begin(),m.end(),is);
    ListNode* k =&m[0];
    for(int i=0;i<m.size()-1;i++){
        m[i].next=&m[i+1];
    }
    m[m.size()-1].next=NULL;
    return k;


}

Вы можете скопировать код и проверить с помощью любого пользовательского ввода, он работает, но возвращает неверный список, когда предоставляется только связанный список размера 2, например. (1-> 2) или, например, (1-> 2 и 3-> 4) он возвращает 0-> 2 и 0-> 2-> 3-> 4 соответственно. (Я знаю, что это имеет плохую временную сложность)


  • Ну алгоритм просто неверный. Кажется, вы предполагаете, что все списки в A имеют длину, равную единице. Однако, каков ваш фактический вопрос? Наверху вроде нет. 03.08.2019
  • Он работает, но возвращает неверный список Я думаю, это означает, что он не работает. Что вам нужно сделать, так это удалить узлы из A по одному (и в правильном порядке) и поместить их в новый список. 03.08.2019
  • как я это предполагаю? Я попробовал пользовательский ввод (1-›2-›3 , 2-›5-›6-›7, 4-›6-›9), он вернул 1-›2-›2-›3-›4-›5 -›6-›6-›7-›9 03.08.2019
  • Хорошо, мои извинения, я неправильно прочитал код. 03.08.2019
  • То, что вы в основном делаете, это объединение всех узлов в один список, а затем его сортировка. Это не то, чем вы должны заниматься. Это полностью упускает суть. И до сих пор нет вопросов. 03.08.2019
  • Я знаю, что он не использует уже отсортированный список, поэтому я написал в последний раз: «Я знаю, что у этого плохая временная сложность». Меня больше беспокоит то, почему он не дает правильный результат для размера ввода 2, как указано в вопрос 03.08.2019
  • Все списки в A отсортированы, поэтому самым нижним узлом является один из узлов в начале одного из списков в A. Найдите этот узел, удалите его из A, добавьте в новый отсортированный список. Затем повторите. Пока все списки в A не опустеют. 03.08.2019
  • Я знаю это решение, все, что я хочу знать, это почему данный алгоритм неверен 03.08.2019

Ответы:


1

Проблема с вашим кодом заключается в том, что возвращаемый вами список состоит из указателей на узлы, которые были уничтожены. Итак, ваш код имеет неопределенное поведение.

ListNode* Solution::mergeKLists(vector<ListNode*> &A) {
    vector<ListNode> m; // this vector contains the nodes of your merged list
    ...
    ListNode* k = &m[0]; // here you take a pointer to the content of m
    ...
        m[i].next = &m[i+1]; // here you make another pointer to the contents of m
    ...
    return k; // here you return that pointer
} // but here m is destroyed

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

03.08.2019
  • Я не возвращаю указатель на вектор, а указатель на ListNode, как указатель головы, он никогда не уничтожается. k хранит адрес 1-го узла, и в цикле for я обновляю следующий указатель каждого узла 03.08.2019
  • ListNode находится в векторе m, а вектор m является локальным для функции, и вы возвращаете указатель на содержимое m. Но если ты не хочешь мне верить, это твой выбор. 03.08.2019
  • Это может быть причиной того, почему он работает во всех других случаях. 03.08.2019
  • Неопределенное поведение (которое у вас есть) означает, что все непредсказуемо. 03.08.2019
  • Я не утверждаю, что вы возвращаете указатель на вектор, но указатель на содержимое векторов, в частности m[0]. И, конечно же, все ваши следующие указатели также указывают на содержимое m. Таким образом, все эти указатели становятся недействительными, как только m уничтожается, что происходит при выходе из функции. 03.08.2019
  • Итак, как мне вернуть указатель? должен ли я создать временный ListNode внутри цикла for, а затем назначить ему указатель ListNode, а затем следующие узлы 03.08.2019
  • Хорошо, если вы делаете это правильно, ваш объединенный список должен повторно использовать узлы, которые находятся в A, поэтому в конце функции A просто будут пустые списки, потому что все узлы были перемещены в новый список. . 03.08.2019
  • Я полагаю, вы могли бы изменить m на vector<ListNode*> m; и удалять узлы с A[i], когда вы нажимаете их на m. 03.08.2019
  • Другим вариантом было бы выделение новых ListNodes (с new), что было бы еще менее эффективным, чем то, что у вас есть в настоящее время. 03.08.2019
  • ListNode* k = новый ListNode(m[0]); ListNode* temp=k; for(int i=1;i‹m.size();i++){ temp-›next= new ListNode(m[i]); temp=temp-›следующий; } temp-›next=NULL; вернуть к; 03.08.2019
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..