Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions 206_ReverseLinkedList/206_ReverseLinkedList.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// data_structures
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};

// Step1
#include <stack>

class Solution {
public:
ListNode* reverseList(ListNode* head) {
std::stack<ListNode*> st;
ListNode *node = head;
ListNode dummy(0);

while (node != nullptr) {
st.push(node);
node = node->next;
}
node = &dummy;
while (!st.empty()) {
node->next = st.top();
st.pop();
node = node->next;
}
node->next = nullptr;
return dummy.next;
}
};

// Step2
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *node = head;
ListNode *prev = nullptr;
ListNode *temp = head;

while (node != nullptr) {
temp = node->next;
node->next = prev;
if (temp == nullptr) {
break;
}
prev = node;
node = temp;
}
return node;
}
};

// Step3
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *node = head;
ListNode *prev = nullptr;

while (node != nullptr) {
ListNode *temp;
temp = node->next;
node->next = prev;

prev = node;
node = temp;
}
return prev;
}
};
109 changes: 109 additions & 0 deletions 206_ReverseLinkedList/206_ReverseLinkedList.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# 206. Reverse Linked List
- 問題文: [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/description/)
- 使用言語: C++
- 次に解く問題: [703. Kth Largest Element in a Stream](https://leetcode.com/problems/kth-largest-element-in-a-stream/description/)

## 知識セット
### 知っていたこと
- 計算量の概念
- Stackの扱い方
- ポインタの扱い方

### 今回調べたこと
-

## Step1 Stack
- 所要時間: 10min.
- 方針: Stackに格納して最後に取り出す
- stackのカテゴリなので一応やってみる
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

私は、これが stack に入っているのは出題意図とは違うと思いますね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同意です。一応実装しましたが、実装自体はstackだと非常に楽だと感じました。
逆にスタックを使うべき場面ってあまり直観的に想像がつかないですが、それこそ再帰だとスタックオーバーしそうなとき、とかかなと考えました。

- 最後のnodeはnextをnullポインタで埋めないといけない
- for文で要素数を使って実行しようと思ったが、要素数は可変だからうまくいかなかった
- コード
```cpp
#include <stack>

class Solution {
public:
ListNode* reverseList(ListNode* head) {
std::stack<ListNode*> st;
ListNode *node = head;
ListNode dummy(0);

while (node != nullptr) {
st.push(node);
node = node->next;
}
node = &dummy;
while (!st.empty()) {
node->next = st.top();
st.pop();
node = node->next;
}
node->next = nullptr;
return dummy.next;
}
};
```
- 計算量
- 時間計算量: O(N)
- 空間計算量: O(N)

## Step2 ポインタ操作
- 所要時間: 20min.
- 方針: ポインタを用いていい感じにreverseする
- 計算量の観点でも実装のわかりやすさからもこっちが第一選択なように思う
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かに再帰で実装できます。なかなかその発想に至らないのはよくなかったです。
あとで試してみようと思います。
最奥まで探索して逆順に返すのは再帰の得意分野ですね🤔

- ロジックが見えづらくなってしまったのでStep3でリファクタリングする
- コード
```cpp
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *node = head;
ListNode *prev = nullptr;
ListNode *temp = head;

while (node != nullptr) {
temp = node->next;
node->next = prev;
if (temp == nullptr) {
break;
}
prev = node;
node = temp;
}
return node;
}
};
```
- 計算量
- 時間計算量: O(N)
- 空間計算量: O(1)

## Step3
- 所要時間: min
- 方針: リファクタリング
- breakは不要で、最後にprevをretすれば足りる
- tempに避難させてnextを書き換え、prev/nodeを同時に進める
- コード
```cpp
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *node = head;
ListNode *prev = nullptr;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

最後に返すオブジェクトが prev なのはあまり直感的ではないと感じました。
c.f., https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.x5w37bodndgj

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そもそもnodeとprevという変数名がreverseする問題設定上わかりづらい設定だったかもしれません。
ご指摘ありがとうございます🙏


while (node != nullptr) {
ListNode *temp;
temp = node->next;
node->next = prev;

prev = node;
node = temp;
}
return prev;
}
};
```
- 計算量
- 時間計算量: O(N)
- 空間計算量: O(1)
1 change: 1 addition & 0 deletions template.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Num. Title
- [Arai60](https://1kohei1.com/leetcode/)
- 問題文: [Title](Url)
- 使用言語: C++
- 次に解く問題: [NextTitle](NextUrl)
Expand Down