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
191 changes: 191 additions & 0 deletions 2_add_two_numbers/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# 2. Add Two Numbers

https://leetcode.com/problems/add-two-numbers/description

C++で書く練習。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

拡張子は、.cc か .cpp にすることが多いです。
あとはいいと思います。


どういう問題か。
Linked Listが2つ与えられる。
それぞれのLinked Listは、数字が格納されている。
逆順から読んだ数字を足し合わせ、それをまた逆順にLinked Listにして返す。

解き方。
1. 2つのLinked Listを走査して数字に直す。
2. その数字を足し合わせる。
3. 足し合わせた数字を逆順にLinked Listにして返す。

1について。
これはatoiの感覚で直せそう。

2について。
これは足すだけ。

3について。
これは、itoaの感覚で逆順にLinked Listにしていけば良さそう。

C言語なら書けそうやけど、C++でどう書くかわからん😥

参考にしたコード
[maeken4さんのコード](https://github.com/maeken4/Arai60/pull/5/files)
[ryousuketcさんのコード](https://github.com/ryosuketc/leetcode_arai60/pull/5/files)
→基数を定数で置くかどうかの話おもろい。
[jey makさんのコード](https://github.com/jeymak-trainee/arai60training/pull/2/files)
→意外とJavaも読める。C++と似てる。
[mysteaさんのコード](https://github.com/potrue/leetcode/pull/5/files)
→Pythonで書かれていた。文脈がわかっているから読めるが、初見じゃまだPythonは読めなさそう。
[nktrさんのコード](https://github.com/nktr-cp/leetcode/pull/6/files)
→この方のコードめちゃくちゃ分かりやすい!!!すごい。
逆順に入っている意図を理解できた。計算したい順番で入ってるんかこれ。

自分でかけそう!

## Comments

### step1
```cpp
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy_head = ListNode();
ListNode *result_tail = &dummy_head;
int carry = 0;
while (l1 || l2 || carry)
{
int value = carry;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

変数名 value は一般的すぎて、何の値が入っているのか想像しにくいと感じます。

if (l1)
{
value += l1->val;
l1 = l1->next;
}
if (l2)
{
value += l2->val;
l2 = l2->next;
}
carry = value / 10;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

処理の始めから value に次々に l1 , l2 の値を足していく処理のようですが、変数の生存期間が長くてなんとなく頭の一時記憶を占める感覚があります。

value %= 10;

result_tail->next = new ListNode(value);
result_tail = result_tail->next;
}
return dummy_head.next;
}
};
```
自分で書こうと思ったが思ったより手が動かなかったので、とりあえず写してみた。
carryが繰り上がりを保持している。
dummy_headは結果のLinked Listの先頭を保持している。
while3つの処理を全部まとめてるの分かりやすい。
俺ならバラバラに走査してしまう。
Cと同じで、CPPも上に構造体の中身を定義しておく必要があるのね。
```cpp
result_tail->next = new ListNode(value);
```
こんなんしていいの?これ気になった。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

なぜ気になったのか言語化することはできますか?

自分の場合は、関数の中で new で確保したメモリを、誰が解放するのか気になりました。 LeetCode の場合は、プログラムの終了時に OS が解放するのに任せるようです。実務のプログラムではメモリーリークとなるため、原則避けたほうがよいと思います。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

左辺はresult_tailの指すオブジェクトのListNode型のメンバーにアクセスしていて、new演算子はオブジェクトへのポインタ型(ListNode)を返すので論理的には問題ないかと思います。

今度こそ自分で書けそう!

*

### step2
```cpp
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy_head = ListNode();
ListNode *result_tail = &dummy_head;
int curry = 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

typoしてますね。

while (l1 || l2 || curry)
{
int val = curry;
if (l1)
{
val += l1->val;
l1 = l1->next;
}
if (l2)
{
val += l2->val;
l2 = l2->next;
}
curry = val / 10;
val = val % 10;
result_tail->next = new ListNode(val);
result_tail = result_tail->next;
}
return dummy_head.next;
}
};
```
自分で書けた!
9分ぐらいかかった。
10出てくるの確かにちょっとだけ気になる。
次は定数で外に出してみよう。


Mainが書けないの良くないなぁ。
Main書く練習もしなあかんけど、しんどいので慣れるまでは写経しよう。
ただ、今回人のコード写してるだけやからちょっとおもしろくない。
自分でかけるようにならんとなぁ。


*

### step3
```cpp
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
#define BASE_NUM 10;
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy_head = ListNode();
ListNode *result_tail = &dummy_head;
int curry = 0;
while (l1 || l2 || curry)
{
int val = curry;
if (l1)
{
val += l1->val;
l1 = l1->next;
}
if (l2)
{
val += l2->val;
l2 = l2->next;
}
curry = val / BASE_NUM;
val = val % BASE_NUM;
result_tail = new ListNode(val);
result_tail = result_tail->next;
}
return dummy_head.next;
}
};
```

なんか通らん。Macroの形が良くないんかな?
```cpp
result_tail = new ListNode(val);
```
next抜けてた😭
8分で書けた。
*
38 changes: 38 additions & 0 deletions 2_add_two_numbers/step1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy_head = ListNode();
ListNode *result_tail = &dummy_head;
int carry = 0;
while (l1 || l2 || carry)
{
int value = carry;
if (l1)
{
value += l1->val;
l1 = l1->next;
}
if (l2)
{
value += l2->val;
l2 = l2->next;
}
carry = val / 10;
value %= 10;

result_tail->next = new ListNode(value);
result_tail = result_tail->next;
}
return dummy_head.next;
}
};
37 changes: 37 additions & 0 deletions 2_add_two_numbers/step2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy_head = ListNode();
ListNode *result_tail = &dummy_head;
curry = 0;
while (l1 || l2 || curry)
{
int val = curry;
if (l1)
{
val += l1->val;
l1 = l1->next;
}
if (l2)
{
val += l2->val;
l2 = l2->next;
}
curry = val / 10;
val = val % 10;
result_tail->next = new ListNode(val);
result_tail = result_tail->next;
}
return dummy_head.next;
}
};
38 changes: 38 additions & 0 deletions 2_add_two_numbers/step3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
#define BASE_NUM 10;
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy_head = ListNode();
ListNode *result_tail = &dummy_head;
int curry = 0;
while (l1 || l2 || curry)
{
int val = curry;
if (l1)
{
val += l1->val;
l1 = l1->next;
}
if (l2)
{
val += l2->val;
l2 = l2->next;
}
curry = val / BASE_NUM;
val = val % BASE_NUM;
result_tail = new ListNode(val);
result_tail = result_tail->next;
}
return dummy_head.next;
}
};