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
84 changes: 84 additions & 0 deletions 2.-Add-Two-Numbers/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
レビューの利便性のため、各ステップで書いたコードはこちらにも転記してみます。

# step1
元のリストに対して非破壊的であるようにしたい。素直に繰り上がりを記録しながら足していく方針で解いた。
```cpp
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy(0, nullptr);
ListNode* tail = &dummy;
int carry = 0;
while (l1 != nullptr || l2 != nullptr || carry != 0) {
int val = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + 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.

下の方の2行と合わせて、これも候補でしょう。(どちらがいいというわけではなく。)

int val = carry;
if (l1) {
    val += l1->val;
    l1 = l1->next;
}
if (l2) {
    val += l2->val;
    l2 = l2->next;
}

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.

ありがとうございます。こちらも意図がわかりやすいですね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

好みの問題ですが、個人的にはこちらの方が読みやすいと思いました。

int digit1 = l1 ? l1->val : 0;
int digit2 = l2 ? l2->val : 0;
int val = digit1 + digit2 + carry;

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.

コメントありがとうございます。おっしゃる通り今の場合ぱっと見で分けたほうが何をやっているかわかりやすいですね。

carry = val / 10;
ListNode* append = new ListNode(val % 10, nullptr);
tail->next = append;
l1 = l1 ? l1->next : nullptr;
l2 = l2 ? l2->next : nullptr;
tail = tail->next;
}
return dummy.next;
}
};
```

# step2
他の人のコードを見る。
- [ryosuketcさんのコード](https://github.com/ryosuketc/leetcode_arai60/blob/2_add_two_numbers/2_add_two_numbers/step3.py)と本質的に同じだがこちらのほうが丁寧に関数や定数を切り出している。
- 他の演算も実装する必要があったら補助関数を設定すると思う。
- 他のコメントでも三項演算子は避けられているようだが、今回のようなnullでないことだけ判定するくらいなら左から右に読みやすいと思うので許されたい…
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Python の三項演算子が A if condition else B というもので分かりにくいんですよね。

C++ はまだましだと思いますが、しかし、使ってきれいになることは実は少ないと思います。

- l1, l2がnullptrだったときだけ使うfakeを置いたら場合分けする部分が集約できた。

```cpp
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy(-1, nullptr);
ListNode* tail = &dummy;
int carry = 0;
while (l1 || l2 || carry) {
// l1, l2がnullptrだった場合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.

なるほど、こうした fake を置くという発想はありませんでした (私も if (!l1) l1 = &fake; の方が読みやすいというのには賛成です)。もうちょっと descriptive な名前でもいいかなと思いましたが、用途が限定的なのでよいですかね。

…と思ってよい名前を少し考えましたが意外に思いつきませんでした。default を一瞬考えたけど予約語っぽいなーと思ったら本当に予約語でした: https://en.cppreference.com/w/cpp/keywords/。

ListNode fake(0);
l1 = l1 ? l1 : &fake;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ぶら下がりでも良ければ下の方が意図がはっきりしていませんか?

l1 = l1 ? l1 : &fake;

if (!l1) l1 = &fake;

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.

どちらが分かりやすいかと言われれば後者ですね…コードゴルフでもないので人が読むコードでは避けようと思います。

l2 = l2 ? l2 : &fake;

int total = l1->val + l2->val + carry;
carry = total / 10;
tail->next = new ListNode(total % 10, nullptr);
tail = tail->next;
l1 = l1->next;
l2 = l2->next;
}
return dummy.next;
}
};

```

# step3
fakeをwhileの外においてみた。
```cpp
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy = ListNode(-1);
ListNode* tail = &dummy;
int carry = 0;

ListNode fake = ListNode(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.

外に出すならば const をより付けたいですね。

while (l1 || l2 || carry) {
l1 = l1 ? l1 : &fake;
l2 = l2 ? l2 : &fake;
int total = l1->val + l2->val + carry;
carry = total / 10;
tail->next = new ListNode(total % 10);

tail = tail->next;
l1 = l1->next;
l2 = l2->next;
}
return dummy.next;
}
};
```
26 changes: 26 additions & 0 deletions 2.-Add-Two-Numbers/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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(0, nullptr);
ListNode* tail = &dummy;
int carry = 0;
while (l1 != nullptr || l2 != nullptr || carry != 0) {
int val = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry;
carry = val / 10;
ListNode* append = new ListNode(val % 10, nullptr);
tail->next = append;
l1 = l1 ? l1->next : nullptr;
l2 = l2 ? l2->next : nullptr;
tail = tail->next;
}
return dummy.next;
}
};
30 changes: 30 additions & 0 deletions 2.-Add-Two-Numbers/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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(-1, nullptr);
ListNode* tail = &dummy;
int carry = 0;
while (l1 || l2 || carry) {
// l1, l2がnullptrだった場合0ノードを一時的に設定する。このブロックを抜けると解放される。
ListNode fake(0);
l1 = l1 ? l1 : &fake;
l2 = l2 ? l2 : &fake;

int total = l1->val + l2->val + carry;
carry = total / 10;
tail->next = new ListNode(total % 10, nullptr);
tail = tail->next;
l1 = l1->next;
l2 = l2->next;
}
return dummy.next;
}
};
30 changes: 30 additions & 0 deletions 2.-Add-Two-Numbers/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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 = ListNode(-1);
ListNode* tail = &dummy;
int carry = 0;

ListNode fake = ListNode(0);
while (l1 || l2 || carry) {
l1 = l1 ? l1 : &fake;
l2 = l2 ? l2 : &fake;
int total = l1->val + l2->val + carry;
carry = total / 10;
tail->next = new ListNode(total % 10);

tail = tail->next;
l1 = l1->next;
l2 = l2->next;
}
return dummy.next;
}
};