-
Notifications
You must be signed in to change notification settings - Fork 0
Create TwoSum.md #8
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # step1 何も見ずに解く | ||
|
|
||
| ## 解答 | ||
| - hashMapを使った実装 | ||
| - partnerという単語がパッと思い浮かんだが分かりやすいだろうか | ||
| - `numToIndex.get()`した値をnullチェックするより、`numToIndex.containsKey()`する方が読み手にとって親切だろうか | ||
| - hashの計算を2回するのがもったいないように感じて最初から`get()`する形で書いた | ||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 大前提として場合によりけりだとは思いますが、個人的には計算時間の最適化と可読性のトレードオフになった場合は可読性を優先したほうがよいのではないかと考えます。 もしパフォーマンスを気にされるのであればベンチマークを取るなどの計測を行った上で読みやすさより速度を優先した、という決定をされるのがよいのかなと思います。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 仰る通りです。また現実問題、ここで時間をケチったところで問題が解決することは無さそうなのでちょっと余計でした。 |
||
| - 計算量 | ||
| - 時間計算量: O(n) | ||
| - 空間計算量: O(n) | ||
| ```java | ||
| class Solution { | ||
| public int[] twoSum(int[] nums, int target) { | ||
| Map<Integer, Integer> numToIndex = new HashMap<>(); | ||
| for(int i = 0; i < nums.length; i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for のあとにスペースを空けることをおすすめします。 参考までにスタイルガイドへのリンクを貼ります。 https://google.github.io/styleguide/javaguide.html#s4.6.2-horizontal-whitespace
上記のスタイルガイドは唯一絶対のルールではなく、複数あるスタイルガイドの一つに過ぎないということを念頭に置くことをお勧めします。また、所属するチームにより何が良いとされているかは変わります。自分の中で良い書き方の基準を持ちつつ、チームの平均的な書き方で書くことをお勧めいたします。 |
||
| int num = nums[i]; | ||
| int partnerNum = target - num; | ||
| Integer partnerIndex = numToIndex.get(partnerNum); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 自分なら int で受けるのですが、好みの問題かもしれません。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 確かに後続の処理では int としてしか使っていないので、この時点で int としておくべきでした。 |
||
| if (partnerIndex != null) { | ||
| return new int[]{partnerIndex, i}; | ||
| } | ||
| numToIndex.put(num, i); | ||
| } | ||
| return new int[]{}; | ||
| } | ||
| } | ||
| ``` | ||
| - 二重にforループを使った総当たり実装 | ||
| - 最初に書いた時、ループのindexが重なっている時に`continue`するのを忘れていた | ||
| - 計算量 | ||
| - 時間計算量: O(n^2) | ||
| - 空間計算量: O(1) | ||
| - よく考えたら空間計算量的には二重ループの方が優れているか | ||
| - 要素数が一定より少なければhashMapの生成などが不要なためこちらの方が高速になるだろう | ||
| ```java | ||
| class Solution { | ||
| public int[] twoSum(int[] nums, int target) { | ||
| for(int i = 0; i < nums.length; i++) { | ||
| for(int j = 0; j < nums.length; j++) { | ||
| if (i == j) { | ||
| continue; | ||
| } | ||
| if (target == nums[i] + nums[j]) { | ||
| return new int[]{i, j}; | ||
| } | ||
| } | ||
| } | ||
| return new int[]{}; | ||
| } | ||
| } | ||
| ``` | ||
| # step2 他の方の解答を見る | ||
| ## 解答 | ||
| - https://github.com/akmhmgc/arai60/pull/8/files | ||
| - よく考えたら内側のループの始点は`i + 1`でよかった | ||
| - それ以前の値は確認済みのため確認不要 | ||
| - また該当がなかった場合は仮の値を何かしら入れておくのが良いだろう | ||
| - 到達することは無いはずだから適当でいいかくらいにstep1では考えてた | ||
| - nullか-1を入れておくのが一般的だろうか | ||
| ```java | ||
| class Solution { | ||
| public int[] twoSum(int[] nums, int target) { | ||
| for (int i = 0; i < nums.length; i++) { | ||
| for (int j = i + 1; j < nums.length; j++) { | ||
| if (target == nums[i] + nums[j]) { | ||
| return new int[]{i, j}; | ||
| } | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 細かいところで恐縮ですが、ここの閉じカッコ"}"と対応するfor文だけインデントがズレてませんか?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 本当ですね。ありがとうございます。 |
||
| // ここに到達することは無いはず | ||
| return new int[]{-1, -1}; | ||
| } | ||
| } | ||
| ``` | ||
| - hashMapを使った実装において処理の流れは一緒だが以下のような書き方も想定できたらよかった | ||
| - ターゲットとある値の差分を`complement`とする | ||
| - Mapのキーとして「走査済みの値」ではなく「ターゲットと走査した値の差分」をセットする | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 確かにそのような解き方もありますね。勉強になりました。 |
||
| - 後で引き算するか先に引き算するかの違い。個人的には今回書いている前者の方が分かりやすいように思う | ||
| - その他二分探索を使用した書き方も考えられる | ||
| - しかし二分探索するためにはソート&元のインデックスを保持する必要があるためこの場合は不適なように感じる | ||
| - この問題の条件で二分探索の方が適する入力のケースってあるだろうか? | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メモリーに片方が乗らないサイズとかですかね。 まあ、私が思うのは、この問題、手で解くとしたらどうするかです。部屋にカードが1000枚あって、和がある値になる組を探せといわれたら、100万回足し算するかですよ。 |
||
| # step3 3回ミスなく書く | ||
| - 所要時間: 4分程度 | ||
| ## 解答 | ||
| - HashMapを使った実装 | ||
| ```java | ||
| class Solution { | ||
| public int[] twoSum(int[] nums, int target) { | ||
| Map<Integer, Integer> numToIndex = new HashMap<>(); | ||
| for(int i = 0; i < nums.length; i++) { | ||
| int num = nums[i]; | ||
| int partnerNum = target - num; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 分かりづらいわけではないですが、個人的には上で述べられている |
||
| Integer partnerIndex = numToIndex.get(partnerNum); | ||
| if (partnerIndex != null) { | ||
| return new int[]{partnerIndex, i}; | ||
| } | ||
| numToIndex.put(num, i); | ||
| } | ||
| return new int[]{-1, -1}; | ||
| } | ||
| } | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
partnerはちょっと違和感ありますね。
https://dictionary.cambridge.org/dictionary/english/partner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
やはり自然な英単語としては
complementになるでしょうか。コメントありがとうございます!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
まあ無理に1単語で表さなくても、「足すとtargetになる数字」、「targetとの差分」みたいな感じで
differenceToTargetとかでも良いかなと思いました。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
良い変数名を例示いただきありがとうございます!
complementより直感的に分かりやすいです。