Conversation
| coins=[1] amount=0 output = 0 | ||
|
|
||
| 何がわからなかったか | ||
| - いわゆる動的計画法での解き方が分からず、思いついた貪欲法でコードを書いたが貪欲法では解けない入力ケースまで思いつかなかった。 |
There was a problem hiding this comment.
こういうのは、極端なのを考えるとできます。
[1001, 1000, 1] で2000を作るとかです。
naoto-iwase
left a comment
There was a problem hiding this comment.
全体的にとても読みやすかったです。
コメントでも丁寧に検討されていて素晴らしいと思いました。
| > メモ探索ではできない | ||
| 自分が詰まったところを表しているのかなと思った。具体的には、メモ化しようとしてamountとコイン枚数を紐づけてキャッシュしようとしたが、この方法は間違っており、メモ化できなかった。 | ||
|
|
||
| - ダイクストラ法というのもこの問題に適用できるらしい。 |
There was a problem hiding this comment.
ダイクストラ法は、雑に言うと BFS を「各辺に非負の重みがある場合」に一般化したもので、始点からの最小コスト経路を求めるアルゴリズムです。
この問題をグラフとして見ると、0 から amount までの各金額を頂点、金額 x から x + coin への辺を重み 1 の有向辺とみなすことで、最小枚数問題は「0 から amount への最短路問題」として書けます。
辺の重みが全て 1 の場合は、ダイクストラの特殊ケースとして単純な BFS で最短手数を求められるので、今回のように BFS で解くので十分そうです。全ての辺のコストを 1 とみなしたダイクストラを使うこともできますが、ややオーバースペックかなという印象です。
| if visited_amount | ||
| .get(current_amount as usize) | ||
| .is_some_and(|is_visited| *is_visited) | ||
| { |
There was a problem hiding this comment.
上までで、current_amount < amountが保証されているのでいるので境界チェック無しでインデックスアクセスしても安全であり、
if visited_amount[current_amount as usize] {
continue;
}くらいの方が読みやすいと感じます。
| return Self::COMBINATION_NOT_FOUND; | ||
| } | ||
| if coins.iter().any(|v| *v < 0) { | ||
| panic!("coins must be contain only positive values"); |
There was a problem hiding this comment.
非常に瑣末ですが、英文法でbeが不要で"...must contain..."ですね。
| - 322-dp-memo.pngにまとめた。 | ||
|
|
||
| 正解してから気づいたこと | ||
| - DP解法においてcoinsに負のコインが含まれるケースに対応できないことに気付くのに時間がかかった。GPT-5.1に聞いて対応できないことは分かったが理由は難しくてよく分からなかった。 |
There was a problem hiding this comment.
直感的な説明として例えば、coins = [-1, 1, 5]、amount=4のとき、金額の小さい順にDPで解いていくと、
| 金額 | 最小枚数 |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 1 |
となります。
しかし、金額5の結果を知ってから、金額4は2枚で払えるとわかります。つまり、「小さい金額から一方向に DPの表を埋めていけばよい」という仮定が成り立たなくなります。
もし負のコインがありえる場合、コストが負の辺も対処可能なベルマンフォード(Bellman–Ford)法などが必要になります。(←金額が負だとしてもコストが負なわけではないのでこの説明は誤りでした。この場合でもおそらくBFSで良さそうです。)ベルマンフォード法はダイクストラ法の一般化と言え、SWEの常識にはおそらく入りません。
問題: 322. Coin Change
次に解く問題: 35. Search Insert Position
ファイルの構成:
./src/bin/<各ステップ>.rsメモ: Big-O記法に現れない定数倍の処理が実行速度に大きな影響を与えているように見えたので、簡易的なベンチマークテストを実施した。