Skip to content

235. Lowest Common Ancestor of a Binary Search Tree#10

Open
ryosuketc wants to merge 1 commit intomainfrom
235_lowest_common_ancestor_of_a_binary_search_tree
Open

235. Lowest Common Ancestor of a Binary Search Tree#10
ryosuketc wants to merge 1 commit intomainfrom
235_lowest_common_ancestor_of_a_binary_search_tree

Conversation

@ryosuketc
Copy link
Owner

235. Lowest Common Ancestor of a Binary Search Tree

https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/

* > まず、原理的に、コンピュータがコードが到達可能か不可能かを判定することは不可能です。これはチューリングマシンの停止性問題は判定できないことからいえます。一方で、Java や Rust などは、コンパイル時に型のチェックを真面目にしていて、到達不能なコードかはある程度判定します。しかし、不完全です。このため、正確に考えると到達不可能な箇所であったとしても、コンパイラには分からない場合が多々あります。こういったときに、そこの行に例外を書くことでコンパイル可能になります。何を言っているかというと、上のような事情ならば、例外を書くのはいいですが、そうでなければ、私はデッドコードは基本的に書かないほうがよいと思っています。(せいぜいコメントでいいでしょう。)
* 結局 `std::unreachable` はありなのかな?個人的には無限ループより良さそうに思うのだけど…。
* あ、これめっちゃ新しい (C++23)。なるほどそれ以前の環境を考えると無限ループなどが選択肢に入ってくるのか。
* 例外はなんか重いから C++ ではあまり使わないというのも聞いたことがある。
Copy link

Choose a reason for hiding this comment

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

「例外は重い」というのは、return と比べれば重いです。
ここをみると char++ * 100万回が 4 ms で、3906回の exception で1秒くらいかかっています。200マイクロ秒かかるということですね。
https://stackoverflow.com/questions/13835817/are-exceptions-in-c-really-slow
私の直感よりもだいぶ遅いのですが、Exception オブジェクトを作ってスタックを巻き戻しながら誰がキャッチするかを探すということになるので、かなり遅いことは確かです。

ただ、Google 社内で使わない理由は、それよりも大域脱出なのでコードが追えなくなるほうが大きいと私は思っています。Chrome の C++ ソースコードは数万ファイルありますから、読んでいて例外が投げてあったら行き先探すのが辛いですね。

Copy link

Choose a reason for hiding this comment

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

自分が英語をちゃんと読めている自信がないのですが、スタイルガイドには「スクラッチからやり始めなければならないとしたら、選択は変わってくるかもしれない。」といった文言が書いてあります。参考まで。

https://google.github.io/styleguide/cppguide.html#Exceptions

Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. Because we'd like to use our open-source projects at Google and it's difficult to do so if those projects use exceptions, we need to advise against exceptions in Google open-source projects as well. Things would probably be different if we had to do it all over again from scratch.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Exception オブジェクトを作ってスタックを巻き戻しながら誰がキャッチするかを探すということになるので、かなり遅いことは確かです。

Exception が (原理的に) なぜ遅いのか、というのを考えたことがありませんでした。なるほど。

大域脱出なのでコードが追えなくなるほうが大きいと私は思っています。Chrome の C++ ソースコードは数万ファイルありますから、読んでいて例外が投げてあったら行き先探すのが辛いですね。

なるほど、確かにこれは辛いですね。


しかしこうした点は C++ 以外の言語 (Java や Python など) ではそこまで忌避されていないように思います。Java はわかりませんが Python だと例外を返すのはごく普通のことだと思うのですが、それはどういった差があるのでしょう…?

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nodchip さんが引用くださったスタイルガイドなんかを参照していると、「思いから使うな」というよりは、「まあ多少重いのは重いんだけどそれ自体は許容範囲で、どちらかというと大規模コードベースを前提にした時の不都合が大きくなるから使うな」という気がしました。
そういう論理であれば、小さいプロジェクトであれば普通に使ってよい気もしましたが、初心者なのでそのあたりの感覚はずれているかもしれません。。

Copy link

Choose a reason for hiding this comment

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

Java や Python はガーベージコレクションがあるのでスタックの解析が不要で、言語がそもそも遅いのです。あと、言語仕様上書かざるを得ないです。

「まあ多少重いのは重いんだけどそれ自体は許容範囲で、どちらかというと大規模コードベースを前提にした時の不都合が大きくなるから使うな」
だいたいそう思います。あと Google 社内はそれを前提として環境構築(例えばコードサーチからして)しているので、不利益は大きくなります。

* > まず、原理的に、コンピュータがコードが到達可能か不可能かを判定することは不可能です。これはチューリングマシンの停止性問題は判定できないことからいえます。一方で、Java や Rust などは、コンパイル時に型のチェックを真面目にしていて、到達不能なコードかはある程度判定します。しかし、不完全です。このため、正確に考えると到達不可能な箇所であったとしても、コンパイラには分からない場合が多々あります。こういったときに、そこの行に例外を書くことでコンパイル可能になります。何を言っているかというと、上のような事情ならば、例外を書くのはいいですが、そうでなければ、私はデッドコードは基本的に書かないほうがよいと思っています。(せいぜいコメントでいいでしょう。)
* 結局 `std::unreachable` はありなのかな?個人的には無限ループより良さそうに思うのだけど…。
* あ、これめっちゃ新しい (C++23)。なるほどそれ以前の環境を考えると無限ループなどが選択肢に入ってくるのか。
* 例外はなんか重いから C++ ではあまり使わないというのも聞いたことがある。
Copy link

Choose a reason for hiding this comment

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

自分が英語をちゃんと読めている自信がないのですが、スタイルガイドには「スクラッチからやり始めなければならないとしたら、選択は変わってくるかもしれない。」といった文言が書いてあります。参考まで。

https://google.github.io/styleguide/cppguide.html#Exceptions

Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. Because we'd like to use our open-source projects at Google and it's difficult to do so if those projects use exceptions, we need to advise against exceptions in Google open-source projects as well. Things would probably be different if we had to do it all over again from scratch.

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
int p_val = p->val;
int q_val = q->val;
std::stack<TreeNode*> nodes;
Copy link

Choose a reason for hiding this comment

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

nodes には高々 1 個までしか要素が詰まれないため、単に TreeNode* で良いように思いました。

Copy link
Owner Author

Choose a reason for hiding this comment

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

これ気づいていませんでした。stack で積んでいく、とぃうよりは単一の node を動かして走査している、と理解すべきでした。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants