Skip to content

322. Coin Change #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

322. Coin Change #41

wants to merge 1 commit into from

Conversation

fhiyo
Copy link
Owner

@fhiyo fhiyo commented Jul 15, 2024


### ②

再帰。inf (とかsys.maxsizeとか) を使うのは少し抵抗があるが処理が簡潔になるのもあり使った。再帰の上限には注意。

Choose a reason for hiding this comment

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

[質問]

inf (とかsys.maxsizeとか) を使うのは少し抵抗がある

こちら、どういった感覚なのか気になります。
下記で議論されている float('inf') よりは math.inf とは違った視点な気がしましたので・・・。
#24 (comment)

Copy link
Owner Author

Choose a reason for hiding this comment

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

感覚といいますか、infの型はfloatなのでintを返すところで使うのに違和感があるな、というのが抵抗がある理由です (というか型ヒントが -> int になってるのは間違いですね...)
sys.maxsizeについてはリンク先のコメントと同じ理由で、それより大きな値が来うる気持ち悪さがある、という感じです。実務でもこの辺りの値を使う判断もあるでしょうし (64bit環境なら) 2**63 - 1を限界に設定するのは実用上問題ないとは思いますが...

Choose a reason for hiding this comment

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

inf は型が float 、sys.maxsize は最大ではないのですね。。
上限の値ってどうするのがいいのかなと思っていたので、参考になりました。
ありがとうございます。

Choose a reason for hiding this comment

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

上限はamount + 1でもよさそうですね。coinの最小の値が1なので解の最大値はamount枚になります。

Copy link
Owner Author

Choose a reason for hiding this comment

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

あ、たしかに...ありがとうございます。

### ③

非再帰のDFS。実行時間が前2つと比べて明らかに遅い (前2つが1s未満に対してこちらは4s〜6sくらい) が、理由がわからなかった...
stは本当はnum_coins_and_amount_stackとかにするだろうか。

Choose a reason for hiding this comment

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

確かに st 気になりました。

Copy link

@hayashi-ay hayashi-ay left a comment

Choose a reason for hiding this comment

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

良いと思います。BFSの回答もいいですね。

```py
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
num_coins_list = [-1] * (amount + 1)

Choose a reason for hiding this comment

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

_listの部分が気になりました。あまり伝わる情報が増えていない気がします。

Choose a reason for hiding this comment

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

日本語で表すと、各金額(amount)ごとに必要なコインの数、みたいな感じかなと思うので自分ならnum_needed_coinsなどにします。

Copy link
Owner Author

Choose a reason for hiding this comment

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

あまり伝わる情報が増えていない気がします。

そうですよねー変数名からリストであることをもうちょい伝えたいなと思ったのですが...でも変数の使われ方を見ればリストであることは分かるので名前に反映しようとしすぎなくてもいいのかもなという気がしてきました。

def coinChange(self, coins: List[int], amount: int) -> int:
num_coins_list = [-1] * (amount + 1)
num_coins_list[0] = 0
for i in range(amount):

Choose a reason for hiding this comment

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

listの添字が単なるインデックス以上に金額という意味を持っているのでiよりamountとかの命名が良いかなと思います。LeetCodeだと関数シグネチャがあらかじめ決まっていてamountが引数で既に使われていますが。。

class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
coins = list(filter(lambda c: c <= amount, coins))
num_coins_list = [-1] * (amount + 1)
Copy link

Choose a reason for hiding this comment

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

大きな数で初期化すれば、if num_coins_list[i] == -1: の判定が消せるようになり、コードがシンプルになると思います。


### ③

非再帰のDFS。実行時間が前2つと比べて明らかに遅い (前2つが1s未満に対してこちらは4s〜6sくらい) が、理由がわからなかった...
Copy link

Choose a reason for hiding this comment

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

最短経路問題で深さ優先探索をすると、無駄な探索をしてしまうと思います。これが原因だと思います。最短経路問題で、かつ枝の距離が 1 のため、 2nd のように幅優先探索を使うとよいと思います。

Copy link

Choose a reason for hiding this comment

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

最短経路なのでダイクストラでもいいですが、全部の距離が1だと幅優先探索になりますね。

def coinChange(self, coins: List[int], target_amount: int) -> int:
coins = list(filter(lambda c: c <= target_amount, coins))
queue = deque([(0, 0)])
seen = set([0])
Copy link

Choose a reason for hiding this comment

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

seen = [False] * (target_amount + 1)
とすると、ハッシュテーブルを使わなくて済むため、少し軽くなると思います。

st = [(0, 0)]
while st:
num_coins, current_amount = st.pop()
num_coins_list[current_amount] = min(num_coins_list[current_amount], num_coins)
Copy link

Choose a reason for hiding this comment

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

st に append() するタイミングで num_coins_list[next_amount] の更新を行い、st から取り出したタイミングで、

if num_coins_list[current_amount] != num_coins:
    continue

とすると、過去に処理した状態より悪い状態に対しての処理をスキップすることができ、少し早くなるかもしれません。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants