Skip to content
Open
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
154 changes: 154 additions & 0 deletions 122. Best Time to Buy and Sell Stock II.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# 進め方

Step1 : 問題を解く。

Step2 : 他の人のPRを参照し、コメントする。

Step3 : 3回続けてエラーが出ないように書く。ドキュメントを参照する。

# 実践

## Step1

### 思考ログ

テストケース

7,1,5,6,3,4

None

1,3,5

1

多分いくつかやり方がある。

①明日の金額が値下がりするなら売る。明日が値上がりなら売らない。(デイトレーダーっぽい)

→ 前日と比べて差が0より大きいなら利益に可算する

時間O(N) 空間O(1)

```python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
assert isinstance(prices, list)
if len(prices) <= 1:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

このブロックはなくても動きますね。

return 0
total_profit = 0
for i in range(1, len(prices)):
total_profit += max(0, prices[i] - prices[i-1])
return total_profit
```

②山で売って、谷で買う。

株の取引なら手数料があることもあると思うので、なるべく売買の回数を減らす方法で。

↓動きません。

初手と終わりが難しい

```python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
assert isinstance(prices, list)
if len(prices) <= 1:
return 0
is_upward = False
result = 0
holding = prices[0]
for i in range(1, len(prices) - 1):
print(holding)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

print(f'i: {i}, holding: {holding}')
みたいにログを出すとデバッグに有用かもしれません。多くの情報をログに出すくらいならデバッガーを使った方がいいかもしれませんが。

diff_next = prices[i+1] - prices[i]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ループ定義でiが1から始まっているので、iとi-1を比べるんだろうなと推測したのでここであれ?となりました。
動かないコードも貼っていただけると読み手にとっていい練習になるのでありがたいです!

# 谷
if not is_upward and diff_next > 0:
is_upward = True
holding = prices[i]
continue
# 山
if is_upward and diff_next < 0:
is_upward = False
result += prices[i] - holding
result += max(0, prices[-1] - holding)
return result

```

詰まったのでAIに直してもらった。Whileのほうが分かりやすい。

```python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
assert isinstance(prices, list):
if len(prices) <= 1:
return 0
total_profit = 0
i = 0
num_prices = len(prices)
while i < num_prices - 1:
# 1. 谷 (Valley) を見つける
while i < num_prices - 1 and prices[i+1] <= prices[i]:
i += 1
bottom = prices[i]
# 2. 山 (Peak) を見つける
while i < n - 1 and prices[i+1] >= prices[i]:
i += 1
peak = prices[i]
total_profit += peak - bottom
Comment on lines +91 to +99
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

この辺は個人的には関数化しますかね。
L96のnはどこから来ました?(num_pricesの間違い?)

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.

レビューありがとうございます。
nはタイポです。
確かに関数化するか迷いました。

return total_profit
```

## Step2

### 同じ問題を解いた人のプルリクを見る

https://github.com/olsen-blue/Arai60/pull/38

- Step3は読みやすい。

https://github.com/nittoco/leetcode/pull/44

- 関数でindexを受け取ると変数名が長くなるが、i = start_index としてシンプルに見えるようにできる

https://github.com/hroc135/leetcode/pull/36

- 同時に更新したほうが自然。
- https://github.com/hroc135/leetcode/pull/36#discussion_r1913384463

https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0

毎日できることは、株を持っているか、お金を持っているかの2択なので、未来が見える人になったとして、どちらがいいかを考えればいいのです。

## Step3

### 3回連続で再現できるようになる

改めて書いてみるとolsen-blueさんの関数名は上手だと感じる。

最小の取引回数で

```python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
assert isinstance(prices, list)
num_prices = len(prices)
if num_prices <= 1:
return 0
profit = 0
i = 0
while i < num_prices - 1:
# 底を見つける
while i < num_prices - 1 and prices[i] >= prices[i+1]:
i += 1
if i == num_prices - 1:
break
Comment on lines +145 to +146
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

この構造は while-else 使うときれいに書けますかね?

profit -= prices[i]
# 頂点を見つける
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

こういうコメントのおかげもあって、一つの(外側の)ループで1連の株売買をしていることがすぐ読み取れますし、手でやるならこうなると思います。
一方、実務で書くなら前日からの値上がり分を累積していく方法の方がシンプルに書けるので、私はそちらを選択すると思いました。

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.

レビューありがとうございます!
実務なら私も累積和を選択すると思います。

while i < num_prices - 1 and prices[i] <= prices[i+1]:
i += 1
profit += prices[i]
return profit
```