Skip to content
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

Two Sum #8

Merged
merged 2 commits into from
Sep 23, 2024
Merged

Two Sum #8

merged 2 commits into from
Sep 23, 2024

Conversation

rihib
Copy link
Owner

@rihib rihib commented Aug 6, 2024

Two Sumを解きました。レビューをお願いいたします。

問題:https://leetcode.com/problems/two-sum/
言語:Go

すでに解いている方々:
colorbox/leetcode#3
Kitaken0107/GrindEasy#4
sakupan102/arai60-practice#12
goto-untrapped/Arai60#2
kzhra/Grind41#1
fhiyo/leetcode#14
TORUS0818/leetcode#13
erutako/leetcode#2
Ryotaro25/leetcode_first60#12
kazukiii/leetcode#12
Yoshiki-Iwasa/Arai60#10
aoshi2025s/leetcode-review#1
seal-azarashi/leetcode#11
hroc135/leetcode#11

Pythonにおける{} vs dict()

odaさんによるとdict()よりも{}のほうがよく使われるとのこと。
su33331/practice#2 (comment)

また、Pylintでもdict()は追加の関数呼び出しが行われるので{}の方が速いため、dict()を使った際は{}を使うようにメッセージが出るようになっているっぽい。
https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/use-dict-literal.html
TORUS0818/leetcode#13 (comment)

Goのエラー処理

error型

Goには例外がなく、エラーを返り値(error型)として返すことが一般的である(「例外」がないからGo言語はイケてないとかって言ってるヤツが本当にイケてない件)。error型は下記のようにビルトインインターフェースとして定義されている。

type error interface {
    Error() string
}

可能であれば、エラー文字列は、エラーを発生させた操作やパッケージを示す接頭辞を持つなどして、その発生元を特定できるようにすべきである。

fmt.Errorfは書式指定子に従って書式を設定し、error型を満たす値として文字列を返す(https://pkg.go.dev/fmt#Errorf )。fmt.Printfと違って標準出力に書き込まれるわけではない。

log

log.Panic, log.Fatal, log.Printなどは、標準エラーに書き込み、各ログメッセージの日付と時刻を表示する。 出力されるメッセージが改行で終わっていない場合、改行を追加する。 Fatal関数は、ログメッセージを書き込んだ後、os.Exit(1)を呼び出す。Panic関数は、ログメッセージを書き込んだ後にpanicを呼び出す。

log.Fatalがログの出力とともにプログラムを異常終了するという設計になってる理由について、Googleではコードベースが巨大なために例外を使うとプログラムの処理を追うのが困難になってしまうため、異常が出たらすぐにプロセスを終了させたいらしく、その際に異常終了したデータも欲しいということでそのような設計になっているらしい(https://x.com/ainsophyao/status/1520934026626109440 )。

Panic / Recover

panicというビルトイン関数は、エラーが回復不能なものでプログラムの実行を継続できない場合に、プログラムの実行を停止するランタイムエラーを作り出す。panicは、任意の型の引数(多くの場合文字列)を1つ取り、プログラムが終了するときに表示される。 また、無限ループから抜けるなど、何か不可能なことが起こったことを示す手段でもある。

実際のライブラリ関数はパニックを避けるべきである。当たり前だが、もし問題を隠したり回避できるのであれば、プログラム全体をダウンさせるよりも、実行を継続させた方が良い。 もしライブラリが本当に実行を継続できないのであれば、パニックを起こすのは仕方がない。

panicが呼び出されると、スライスのインデックスが範囲外であるとか、型アサーションに失敗するといった実行時エラーに対して暗黙的に呼び出される場合も含めて、現在の関数の実行を直ちに停止し、ゴルーチンのスタックの巻き戻しを開始し、途中で遅延された関数を実行する。 巻き戻しがゴルーチンのスタックの最上位に達すると、プログラムは終了するが、ビルトイン関数のrecoverを使えば、ゴルーチンの制御を取り戻し、通常の実行を再開することができる。

recoverの呼び出しは巻き戻しを停止し、panicに渡された引数を返す。 巻き戻し中に実行されるコードは遅延(deferred)関数の内部だけであるため、recoverは遅延関数の内部でのみ有用である。

func safelyDo(work *Work) {
    defer func() {
        if err := recover(); err != nil {
            log.Println("work failed:", err)
        }
    }()
    do(work)
}

@rihib
Copy link
Owner Author

rihib commented Aug 6, 2024

mapはhashではなく平衡二分探索木なのですね。。。(C++の場合)
Ryotaro25/leetcode_first60#12 (comment)

気になったので調べてみたのですが、Goのmapの実装はハッシュテーブルらしいです。
https://zenn.dev/smartshopping/articles/5df9c3717e25bd

mapの内部実装

@rihib
Copy link
Owner Author

rihib commented Aug 6, 2024

わかりやすさで考えるとnumsMapより、numToIdxの方が情報量があるので良さそう。

そうするとそれに合わせてnではなくnumとしたほうがよりわかりやすそう?

Copy link

@kazukiii kazukiii left a comment

Choose a reason for hiding this comment

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

良いと思います!

@rihib rihib merged commit 7d3c3b7 into main Sep 23, 2024
@rihib rihib deleted the two_sum branch September 23, 2024 13:14
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.

5 participants