-
Notifications
You must be signed in to change notification settings - Fork 0
739. Daily Temperatures #10
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,137 @@ | ||
| ## step1 とりあえず解く | ||
| - 計算量 | ||
| - 時間:O(N^2) | ||
| - 空間:O(N) | ||
| - 時間計算量をO(N)にする解決策を思いつけず、安直に全探索 | ||
|
|
||
| ```java | ||
| class Solution { | ||
| public int[] dailyTemperatures(int[] temperatures) { | ||
| int[] ans = new int[temperatures.length]; | ||
| for (int i = 0; i < temperatures.length - 1; i++) { | ||
| for (int j = i + 1; j < temperatures.length; j++) { | ||
| if (temperatures[i] < temperatures[j]) { | ||
| ans[i] = j - i; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| return ans; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## step2 他の人の回答を見て気になるところを修正 | ||
| - 計算量 | ||
| - 時間: O(N) | ||
| - 空間: O(N) | ||
| - 単調増加、単調減少するように要素が並べられたStackはMonotonic Stackというらしい | ||
| - for文の中にwhile文があるためぱっと見時間計算量がO(N^2)に見えたが、各要素一度しかpop, pushされないためO(N)になる | ||
| - 単にstackに積むだけではなく、stackに積む前に積むあたいがstackの一番上の値より大きいか確認する | ||
| - 大きければ、stackからpopする | ||
| - この一連の動作により単調減少のstackが作れる | ||
| - stackに積むのはindexだけでいいかなと思ったが、おそらくわかりやすさのために温度もセットで積んでいる | ||
|
|
||
| ```java | ||
| class Solution { | ||
| public int[] dailyTemperatures(int[] temperatures) { | ||
| ArrayDeque<int[]> stack = new ArrayDeque<>(); | ||
|
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[] の 0 番目と 1 番目にどのような値が含まれているのか、やや分かりづらいように感じました。 クラスやレコードクラスを作り、変数名やアクセサメソッド名で、どのような値が含まれているか、読み手にとって分かりやすくするとよいと思いました。
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[] ans = new int[temperatures.length]; | ||
|
|
||
| for (int t = 0; t < temperatures.length; t++) { | ||
|
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. t という変数名が何を表しているのわかりませんでした。短いスコープで、インデックスを表す 1 文字の変数には i がよく使われると思います。また、もう少しスコープが長くなる場合は、 i ですと何を表すか分かりにくくなると思います。その場合は、 day 等、中にどのような値が含まれているかが分かる英単語・英語句にするとよいと思います。
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. ありがとうございますm
今回は上記コメントでいただき、実装したRecordクラスのフィールド名に合わせてdayとしました。 |
||
| int temperature = temperatures[t]; | ||
| while (!stack.isEmpty() && temperature > stack.peekLast()[0]) { | ||
| int[] pairs = stack.pollLast(); | ||
| ans[pairs[1]] = t - pairs[1]; | ||
| } | ||
| stack.add(new int[]{temperature, t}); | ||
| } | ||
| return ans; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| - 計算量 | ||
| - 時間: O(N) | ||
| - 空間: O(N) | ||
| - 上記とは異なり右から(配列の後ろから)みていく方法 | ||
| - ただ配列を右から見ていくというのが直感的ではない、若干認知負荷が高く感じてしまった | ||
|
|
||
| ```java | ||
| class Solution { | ||
| public int[] dailyTemperatures(int[] temperatures) { | ||
| int length = temperatures.length; | ||
| Deque<Integer> stack = new ArrayDeque<>(); | ||
|
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. stack という変数名からは、中にどのような値が含まれているか分かりにくく感じました。 decreasingTemperatureIndices 等、中に含まれる値を想起しやすい名前を付けるとよいと思います。
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[] result = new int[length]; | ||
|
|
||
| for (int currentIndex = length - 1; currentIndex >= 0; currentIndex--) { | ||
| while (!stack.isEmpty() && temperatures[stack.peek()] <= temperatures[currentIndex]) { | ||
| stack.pop(); | ||
| } | ||
|
|
||
| if (!stack.isEmpty()) { | ||
| result[currentIndex] = stack.peek() - currentIndex; | ||
| } | ||
|
|
||
| stack.push(currentIndex); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## step3 3回とく | ||
| - step2の配列の左から見ていく方法解いた | ||
|
|
||
| ```java | ||
| class Solution { | ||
| public int[] dailyTemperatures(int[] temperatures) { | ||
| int[] ans = new int[temperatures.length]; | ||
| Deque<int[]> stack = new ArrayDeque<>(); | ||
|
|
||
| for (int t = 0; t < temperatures.length; t++) { | ||
| int temperature = temperatures[t]; | ||
| while (!stack.isEmpty() && stack.peekLast()[1] < temperature) { | ||
| int[] pair = stack.pollLast(); | ||
| ans[pair[0]] = t - pair[0]; | ||
| } | ||
| stack.add(new int[]{t, temperature}); | ||
| } | ||
| return ans; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## step4 いただいた指摘を元に書き直す | ||
| - step1で書いたコード関していただいた指摘: | ||
| >クラスやレコードクラスを作り、変数名やアクセサメソッド名で、どのような値が含まれているか、読み手にとって分かりやすくするとよいと思いました。 | ||
| >https://github.com/yamashita-ki/codingTest/pull/10#discussion_r2358390279 | ||
|
|
||
| >t という変数名が何を表しているのわかりませんでした。短いスコープで、インデックスを表す 1 文字の変数には i がよく使われると思います。また、もう少しスコープが長くなる場合は、 i ですと何を表すか分かりにくくなると思います。その場合は、 day 等、中にどのような値が含まれているかが分かる英単語・英語句にするとよいと思います。 | ||
| >https://github.com/yamashita-ki/codingTest/pull/10#discussion_r2358402338 | ||
|
|
||
| - いただいた指摘通り、Record型を新たに定義し、for文の中で使われる変数名を修正する | ||
|
|
||
| ```java | ||
| class Solution { | ||
|
|
||
| private record DayTemperature(int day, int temperature) {} | ||
|
|
||
| public int[] dailyTemperatures(int[] temperatures) { | ||
| Deque<DayTemperature> stack = new ArrayDeque<>(); | ||
| int[] ans = new int[temperatures.length]; | ||
|
|
||
| for (int day = 0; day < temperatures.length; day++) { | ||
| int temperature = temperatures[day]; | ||
| while (!stack.isEmpty() && temperature > stack.peekLast().temperature()) { | ||
| DayTemperature previousDay = stack.pollLast(); | ||
| ans[previousDay.day()] = day - previousDay.day(); | ||
| } | ||
| stack.add(new DayTemperature(day, temperature)); | ||
| } | ||
| return ans; | ||
| } | ||
| } | ||
|
|
||
| ``` | ||
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.
この stack 何が入っているかというと、「日付と温度の組で、その日よりも高温になった日がまだ出てきていないもの、日付の昇順、温度の降順」ですかね。コードがこのことを発見するパズルになっているという言い方もできるでしょう。どういうヒントを与えたら一番そのことに容易に気がつくでしょうか。
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つ目にstackの中身をRecord型で定義し日付と温度の組であることを分かりやすくすることがあると思います。
2つ目にstackという変数名を変更し、この変数の使われ方を明確化するというのがあるかと思います。
stackに変わる変数名の候補としては、これら全ての特性を表現するのは難しいと思いつつ下記のような候補があるかと思います。
以上から、野田さんに提案いただいたdecreasingTemperatureIndicesが最適なのかなと思いました。
ヒントを与えるなら、という視点から他者にいかにして自分の組んだパズルを理解してもらうかという思考に至り、参考になりました。
ありがとうございますmm
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.
私は unresolved 気に入りました。
unresolvedDays くらいで日付のみ載せるなどでもいいかもしれません。
いずれにせよ工夫や趣味で評価はぶれるものですが、パズルのヒントを(コメントも利用しながら)どう与えるか考えれば間違いはないでしょう。(管理しやすいコードにして、エンジニアリングをしやすくするという目的に沿っています。)