Skip to content
Open
Show file tree
Hide file tree
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
33 changes: 33 additions & 0 deletions 121. Best Time to Buy and Sell Stock/solution1_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* ・概要
* 自力解法
* 解法は全探索、DPすぐに思い浮かんだ。5分ほどでAC
* DP解法としては、あるindexの要素に着目したとき、利益はそれまでの最低の価格で買った時との差分であるので、最低値のみを保持して毎回現在との差分を取れば良い。
* これは1回の配列走査でおわるのでO(n)となり、変数だけもっておけばいいので空間もO(1)
*
* ・計算量
* O(n):nは配列の要素数
* O(1)
*
* ・その他
* せっかくなのであとで、全探索versionもかく。
* ループは0でなく1からで良さそう。
*/

public class solution1_1 {
public int maxProfit(int[] prices) {
if (prices.length == 0 || prices.length == 1) {
return 0;
}
int maxProfit = 0;
int minPriceBefore = prices[0];
for (int i = 0; i < prices.length; i++) {
int currentMaxProfit = Math.max(0, prices[i] - minPriceBefore);
maxProfit = Math.max(maxProfit, currentMaxProfit);
if (prices[i] < minPriceBefore) {
minPriceBefore = prices[i];
}
}
return maxProfit;
}
}
31 changes: 31 additions & 0 deletions 121. Best Time to Buy and Sell Stock/solution1_2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* ・概要
* 自力解法
* 全探索バージョン、二重ループ
* DP解法としては、あるindexの要素に着目したとき、利益はそれまでの最低の価格で買った時との差分であるので、最低値のみを保持して毎回現在との差分を取れば良い。
* これは1回の配列走査でおわるのでO(n)となり、変数だけもっておけばいいので空間もO(1)
*
* ・計算量
* O(n^2):今回は最大でn=10^5となるので、最大10Gかかる。Macだとクロック数が数GHzなので、単純計算でも3sくらいはかかる。
* Javaのオーバーヘッドを加味して、だいたい3倍くらいかかる(10sくらい)という予想
* 以前共有いただいたJavaとかのベンチマーク
* https://benchmarksgame-team.pages.debian.net/benchmarksgame/box-plot-summary-charts.html
* https://github.com/niklas-heer/speed-comparison
*
*
*/

public class solution1_2 {
public int maxProfit(int[] prices) {
if (prices.length == 0 || prices.length == 1) {
return 0;
}
int maxProfit = 0;
for (int i = 0; i < prices.length; 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.

nit: 私だったらijsell_i, buy_iとしてもう少し情報を乗せるかなと思いました。

The Art of Readable Codeにそんなことが載っていたな...と思い読み返してみたところ、

...But sometimes there are better iterator names than i, j, and k.

とし、3重ループの例を挙げて

if (clubs[i].members[k] == users[j])

とするよりも

if (clubs[club_i].members[member_i] == users[user_i])

とした方がわかりやすいと指摘されていました。Best Time to Buy and Sell Stockの場合同じpricesにアクセスしているので、The Art of Readable Codeの例とは若干設定が異なるのですが、参考まで。

for (int j = 0; j < i; j++) {
maxProfit = Math.max(maxProfit, prices[i] - prices[j]);
}
}
return maxProfit;
}
}
43 changes: 43 additions & 0 deletions 121. Best Time to Buy and Sell Stock/solution2_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* https://github.com/irohafternoon/LeetCode/pull/40/files
* たしかにif文で分岐させると意味合い的にもわけられていいかも
*
* https://github.com/huyfififi/coding-challenges/pull/4/files
* たしかに後ろからみていくのも悪くない。直感的なのは左からみていくだが、(未来 - 過去)という構図がわかりやすいなと思った。
*
* https://github.com/seal-azarashi/leetcode/pull/35/files
* 大体同じ
*
*
* 以下では後ろからみていく実装を行う。
*
* ・計算量
* time: O(n), space: O(1)

* ・その他
* maxPriceInFutureはやりすぎかも、maxPriceだけでも十分伝わりそう
*
* https://github.com/colorbox/leetcode/pull/6/files
* https://github.com/goto-untrapped/Arai60/pull/58/files#r1782742318
* 関数型的考え、scanlを調べたところ、累積結果をすべて返す関数らしく、scanl (+) 0 [1, 2, 3, 4] -- => [0, 1, 3, 6, 10], この例だと累積和だ
* ということで最小値と最大値を累積していき、最後にその結果の配列を元にprofitをみていくことだと解釈した。

*/

public class solution2_1 {
public int maxProfit(int[] prices) {
if (prices.length == 0 || prices.length == 1) {
return 0;
}
int maxProfit = 0;
int maxPriceInFuture = prices[prices.length - 1];
for (int i = prices.length - 2; i >= 0; i--) {
if (maxPriceInFuture < prices[i]) {
maxPriceInFuture = prices[i];
continue;
}
maxProfit = Math.max(maxProfit, maxPriceInFuture - prices[i]);
}
return maxProfit;
}
}