Skip to content

Create 0_121. Best Time to Buy and Sell Stock.md#40

Open
irohafternoon wants to merge 1 commit intomainfrom
121.-Best-Time-to-Buy-and-Sell-Stock
Open

Create 0_121. Best Time to Buy and Sell Stock.md#40
irohafternoon wants to merge 1 commit intomainfrom
121.-Best-Time-to-Buy-and-Sell-Stock

Conversation

@irohafternoon
Copy link
Copy Markdown
Owner

Copy link
Copy Markdown

@huyfififi huyfififi left a comment

Choose a reason for hiding this comment

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

良いと思います!コードもわかりやすく、引っかかるところもなかったです!

#include <vector>

class Solution {
public: int maxProfit(const std::vector < int > & prices) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

さらっと Google C++ Style GuideLLVM Coding Standardsをざっと眺めると、std::vector<int>& pricesと、vector, <, int周りにスペースがない方が一般的なのかな?と思います。私自身もスペースがあるスタイルは見た記憶はないですね。C++に明るくないので、私の感覚が誤っている可能性は否めませんが😅
ところで、広く使われているC++のformatterとかあるのでしょうか 🤔 広く許容されるスタイル感覚が身につくまで、formatter・linterを使用するのは1つの手段ですよね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。LeetCode上で書いたものをこのgithubに転記すると、インデントがおかしくなる事象があったので、最後にフォーマッターを使ったのですが、そこであまり見られない形になってしまったことに気づきませんでした。
https://www.codexize.com/tools/cpp-formatter
このサイトなどは一般的な形に整えられるようなので、こちらを使うことに統一しようと思います

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

C++ はパースするためには include 含め頭から読む必要があります。

型か分からないと整形も難しいんですね。。

4分,4分,4分で3回Accept

#### 2周目の宿題
- C++のクラスについて理解を深める(仮装関数,this,継承など)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

どうでもいいことなのですが、仮想関数のtypoですね。



計算量
- 時間計算量 O(N) N = 10^5ステップの時 10マイクロ秒
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

実行時間は環境によって変わりそうなので、手元の環境ならそう明記した方が厳密かもしれませんね。

Copy link
Copy Markdown
Owner Author

@irohafternoon irohafternoon May 12, 2025

Choose a reason for hiding this comment

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

ありがとうございます。手元の値でなく、一般的にc++の計算ステップを10^9回/秒と概算したときの値の見積もりで、その旨明記するべきでした

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1e5 / 1e9 = 1e-4 = 100マイクロ秒ではないでしょうか?
また、C++の計算ステップ数は1e8回/秒と見積もった方が正確になるかもしれません。
https://discordapp.com/channels/1084280443945353267/1262688866326941718/1346058939674005575

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

この場合のループは、私の推測では30クロックかからないと思います。
タイトなループの部分を見ると、
prices[i] を取ってくる、引き算、max, min で回りますね。
x86 では、LEA で取ってきて、SUB で引き算。max, min については CMOVcc という命令があって、CMP で比較した後のフラグで代入の有無を決められます。分岐予測もできそうです。
よって、10命令以下で回りそうです。
(ARM は CSEL があるようです。)
なので、この場合は、1e9 でもいけそうと感じます。(間違っているかもしれません。測ってみてください。)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@hroc135 @oda
レビューありがとうございます。また返信が遅くなりすみません。

1e5 / 1e9 = 1e-4 = 100マイクロ秒ではないでしょうか?

こちらは記載誤りでした。指摘ありがとうございます。

実行時間については今まで測ったことがなかったので調べながら実行してみました。
環境は個々ののPCだと再現性が低いかなと思い、オンライン上の環境を使用しました。
https://paiza.io/ja/projects/new

計測はstd::chronoを使用しています

#include <iostream>
#include <chrono> 
#include <algorithm>
#include <vector>
#include <random>

class Solution {
    public: int maxProfit(const std::vector < int > & prices) {
        if (prices.empty()) {
            return 0;
        }
        int max_profit = 0;
        int lowest_price_ever = prices[0];
        for (int i = 1; i < prices.size(); i++) {
            // 昨日までの最安値の今日の値を比べる
            max_profit = std::max(max_profit, prices[i] - lowest_price_ever);
            lowest_price_ever = std::min(lowest_price_ever, prices[i]);
        }
        return max_profit;
    }
};


int main() {
    //  LeetCodeの制限と同じ制限で各priceの値は0以上10^4以下
    int price_limit = 10000;
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> distrib(0, price_limit);
    //乱数で入力のpricesを作成、配列のサイズは10^5
    int size = 100000;
    std::vector <int> prices;
    for (int i = 0; i < size ; ++i) {
        int random_number = distrib(gen);
        prices.push_back(random_number);
    }
    Solution sol;
    // 測定開始
    auto start = std::chrono::high_resolution_clock::now();
    // 測定部分
    int result = sol.maxProfit(prices);
    // 測定終了
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << result << std::endl;

    // 経過時間を計算
    // std::chrono::duration_cast<std::chrono::nanoseconds> を使用してナノ秒単位に変換
    auto duration_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
    double time = duration_ns.count();
    // 結果の表示
    std::cout << "処理にかかった時間: " << time << " ナノ秒" << std::endl;
    std::cout << "1回当たり"<< time / size << "ナノ秒かかる"<< endl;
    
    return 0;
}

これを実行すると、サイズ10000の配列に対して結果が

処理にかかった時間: 84083 ナノ秒
1回当たり0.84083ナノ秒かかる

のようになりました。1回当たり1ナノ秒を切っているので、一秒間に1e9回以上回すことが可能のようです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

return 0;
}
int max_profit = 0;
int lowest_price_ever = prices[0];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

lowest_price_everって変数名いいですね!真似したいです



- ドキュメント系

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

throw std::invalid_argument("Price cannot be negative");
}
if (prices[i] < lowest_price_ever) {
lowest_price_ever = prices[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.

step2のコードのようにここで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.

4 participants