Problem p02265 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <iostream>
#include <memory>

using namespace std;

template <typename T> class Node {
private:
  T _key;
  shared_ptr<Node<T>> _next;
  weak_ptr<Node<T>> _prev;

public:
  Node(T k) : _key(k), _next(nullptr), _prev() {}

  T key() const { return _key; }
  shared_ptr<Node<T>> next() const { return _next; }
  shared_ptr<Node<T>> prev() const { return shared_ptr<Node<T>>(_prev); }

  bool is_first() const { return _prev.expired(); }
  bool is_last() const { return _next.get() == nullptr; }

  void set_first() { _prev = weak_ptr<Node<T>>(); }
  void set_last() { _next = nullptr; }

  void set_next(shared_ptr<Node<T>> next) { _next = next; }

  void set_prev(shared_ptr<Node<T>> prev) { _prev = weak_ptr<Node<T>>(prev); }
};

template <typename T> class DoublyLinkedList {
private:
  shared_ptr<Node<T>> _first;
  shared_ptr<Node<T>> _last;

public:
  DoublyLinkedList() : _first(nullptr), _last(nullptr) {}

  void insertNode(T key) {
    auto n = make_shared<Node<T>>(key);

    if (is_empty()) {
      _first = n;
      _last = n;
    } else {
      _first->set_prev(n);
      n->set_next(_first);
      _first = n;
    }
  }

  void deleteNode(T key) {
    auto n = _first;
    while (n != nullptr) {
      if (n->key() == key) {
        if (n->is_first() && n->is_last()) {
          clear();
        } else if (n->is_first()) {
          deleteFirst();
        } else if (n->is_last()) {
          deleteLast();
        } else {
          auto next = n->next();
          auto prev = n->prev();
          prev->set_next(next);
          next->set_prev(prev);
        }
        break;
      }
      n = n->next();
    }
  }

  void deleteFirst() {
    if (_first->is_last()) {
      clear();
    } else {
      auto next = _first->next();
      _first = next;
      next->set_first();
    }
  }

  void deleteLast() {
    if (_last->is_first()) {
      clear();
    } else {
      auto prev = _last->prev();
      _last = prev;
      prev->set_last();
    }
  }

  bool is_empty() const { return _first.get() == nullptr; }
  void clear() {
    _first = nullptr;
    _last = nullptr;
  }

  string to_string() {
    auto n = _first;
    string s;
    while (n != nullptr) {
      s += std::to_string(n->key());
      if (n != _last)
        s += " ";
      n = n->next();
    }
    return s;
  }
};

int main() {
  int n;
  cin >> n;

  DoublyLinkedList<int> list;

  for (int i = 0; i < n; i++) {
    string op;
    cin >> op;

    if (op == "insert") {
      int in;
      cin >> in;
      list.insertNode(in);
    } else if (op == "delete") {
      int in;
      cin >> in;
      list.deleteNode(in);
    } else if (op == "deleteFirst") {
      list.deleteFirst();
    } else if (op == "deleteLast") {
      list.deleteLast();
    }
  }

  cout << list.to_string() << endl;
  return 0;
}

Fixed submission:
#include <iostream>
#include <memory>

using namespace std;

template <typename T> class Node {
private:
  T _key;
  shared_ptr<Node<T>> _next;
  weak_ptr<Node<T>> _prev;

public:
  Node(T k) : _key(k), _next(nullptr), _prev() {}

  T key() const { return _key; }
  shared_ptr<Node<T>> next() const { return _next; }
  shared_ptr<Node<T>> prev() const { return shared_ptr<Node<T>>(_prev); }

  bool is_first() const { return _prev.expired(); }
  bool is_last() const { return _next.get() == nullptr; }

  void set_first() { _prev = weak_ptr<Node<T>>(); }
  void set_last() { _next = nullptr; }

  void set_next(shared_ptr<Node<T>> next) { _next = next; }

  void set_prev(shared_ptr<Node<T>> prev) { _prev = weak_ptr<Node<T>>(prev); }
};

template <typename T> class DoublyLinkedList {
private:
  shared_ptr<Node<T>> _first;
  shared_ptr<Node<T>> _last;

public:
  DoublyLinkedList() : _first(nullptr), _last(nullptr) {}

  void insertNode(T key) {
    auto n = make_shared<Node<T>>(key);

    if (is_empty()) {
      _first = n;
      _last = n;
    } else {
      _first->set_prev(n);
      n->set_next(_first);
      _first = n;
    }
  }

  void deleteNode(T key) {
    auto n = _first;
    while (n != nullptr) {
      if (n->key() == key) {
        if (n->is_first() && n->is_last()) {
          clear();
        } else if (n->is_first()) {
          deleteFirst();
        } else if (n->is_last()) {
          deleteLast();
        } else {
          auto next = n->next();
          auto prev = n->prev();
          prev->set_next(next);
          next->set_prev(prev);
        }
        break;
      }
      n = n->next();
    }
  }

  void deleteFirst() {
    if (_first->is_last()) {
      clear();
    } else {
      auto next = _first->next();
      _first = next;
      next->set_first();
    }
  }

  void deleteLast() {
    if (_last->is_first()) {
      clear();
    } else {
      auto prev = _last->prev();
      _last = prev;
      prev->set_last();
    }
  }

  bool is_empty() const { return _first.get() == nullptr; }
  void clear() {
    _first = nullptr;
    _last = nullptr;
  }

  string to_string() {
    auto n = _first;
    string s;
    while (n != nullptr) {
      s += std::to_string(n->key());
      if (n != _last)
        s += " ";
      n = n->next();
    }
    return s;
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  cin >> n;

  DoublyLinkedList<int> list;

  for (int i = 0; i < n; i++) {
    string op;
    cin >> op;

    if (op == "insert") {
      int in;
      cin >> in;
      list.insertNode(in);
    } else if (op == "delete") {
      int in;
      cin >> in;
      list.deleteNode(in);
    } else if (op == "deleteFirst") {
      list.deleteFirst();
    } else if (op == "deleteLast") {
      list.deleteLast();
    }
  }

  cout << list.to_string() << endl;
  return 0;
}