-
Notifications
You must be signed in to change notification settings - Fork 0
35. Search Insert Position #28
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,90 @@ | ||
| ### Step1 | ||
|
|
||
| - smallerの設定を0にしてしまった。最初の要素がtargetより大きかったら意味ない | ||
| - larger_or_equalを返すかsmallerを返すかでindexの計算がこんがらがり頭を使った、苦労した | ||
| - smallerに-1を使うのがお行儀が悪いのかはよくわからない???(Atcoderとかのコードだとよくあるけどやばいのかも) | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def searchInsert(self, nums: List[int], target: int) -> int: | ||
| larger_or_equal = len(nums) | ||
| smaller = -1 | ||
| while larger_or_equal - smaller > 1: | ||
| mid = (larger_or_equal + smaller) // 2 | ||
| if nums[mid] >= target: | ||
| larger_or_equal = mid | ||
| else: | ||
| smaller = mid | ||
| return larger_or_equal | ||
| ``` | ||
|
|
||
| ## Step2 | ||
|
|
||
| - 二分探索について。しっくりできていない。[この辺の議論](https://discord.com/channels/1084280443945353267/1192736784354918470/1199018938005213234)を拝見。 | ||
| - 区間で考えるというアイデアがなかった | ||
| - 理解に時間がかかったが 閉開区間の場合 | ||
|
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. 半開区間でしょうか…。 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. 検索すると用例が数例ありましたが、ほぼ使わない言葉な気がしますね。
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. なるほど、そうなんですね、ありがとうございます |
||
| - 最後の状態は、「見ている区間がない」状態にする←これを誤解してた | ||
| - 閉開区間だったら、left = rightになればOK | ||
| - 今見ているもの(mid)は、必ず区間に含まないものとしてどちらかに寄せる | ||
| - そうしないと、例えばleft = midの時区間が永遠に減らないかも | ||
| - 今回はinsert_leftなので、targetとnums[mid]がイコールであるならばrightを動かして、みている区間を左に寄せる | ||
| - left ≤ mid < rightなので | ||
| - leftを動かすとき、必ず区間を減らすにはleft = mid + 1 | ||
| - rightを動かす時、right = midにしても区間は必ず1減る | ||
| - mid = (left + right)//2 とすればleft ≤ mid < rightは満たす | ||
| - この辺も拝見 | ||
| - bisectのコード https://github.com/python/cpython/blob/3.12/Lib/bisect.py | ||
| - 上の議論と一緒のコードでした | ||
| - elifよりelseが良い | ||
| - https://github.com/SuperHotDogCat/coding-interview/pull/9/files | ||
| - if文、nums[mid] < targetという向きの方がtarget > nums[mid]よりスッキリするかも | ||
| - whileの中もright > leftがいいかも | ||
|
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. 個人的には「右」という変数が左側にあるのは特殊な状況に見えます。 |
||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def searchInsert(self, nums: List[int], target: int) -> int: | ||
| left = 0 | ||
| right = len(nums) | ||
| while right > left: | ||
| mid = (left + right) // 2 | ||
| if nums[mid] < target: | ||
| left = mid + 1 | ||
| else: | ||
| right = mid | ||
| return left | ||
| ``` | ||
|
|
||
| ## Step3 | ||
|
|
||
| ```python | ||
|
|
||
| class Solution: | ||
| def searchInsert(self, nums: List[int], target: int) -> int: | ||
| left = 0 | ||
| right = len(nums) | ||
| while right > left: | ||
|
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. 個人的には |
||
| mid = (left + right) // 2 | ||
| if nums[mid] < target: | ||
| left = mid + 1 | ||
| else: | ||
| right = mid | ||
| return left | ||
| ``` | ||
|
|
||
| ## Step4 | ||
| ```python | ||
|
|
||
| class Solution: | ||
| def searchInsert(self, nums: List[int], target: int) -> int: | ||
| left = 0 | ||
| right = len(nums) | ||
| while left < right: | ||
| mid = (left + right) // 2 | ||
| if nums[mid] < target: | ||
| left = mid + 1 | ||
| else: | ||
| right = mid | ||
| return left | ||
| ``` | ||
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.
AtCoderやLeetCodeで良く見るコードがアプリケーションエンジニアとして良いコードではないなという所感があります。
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.
これは開区間でやっていることに相当するので、分かってやっているならいいですが、分からずやっているととにかく怖いです。数学でもあるんですよ。なんか証明はそれっぽいが違和感がある。ちょっと質問してみると何も分かっていない事が分かるというのが。
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.
ありがとうございます。あーそれでいうと、過去にAtcoderで自分が書いてたときに思ってたのは、「とりあえずleftのindexを小さくしたいけど、小さくしすぎるとmidが範囲外になるしこれくらいにしとくか」だったので全然わかってなかったですね…
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.
smaller < answer <= larger_or_equal を満たすというのが不変条件ですね。answer は配列の中で同じ値またはそれ以上となる一番左の位置です。知りたいのは分かって書いているかです。
Uh oh!
There was an error while loading. Please reload this page.
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.
https://qiita.com/drken/items/97e37dd6143e33a64c8c
なんか過去に読んだ記事で「めぐる式二分探索」と言うのがあって、最初に自分が書いたときもそれで、「rightは常に満たす」「leftは常に満たさない」と言う考えのもと、やってました(この記事の2章)
なのでこれを書いたときには、閉区間というイメージは頭の中になかったです
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.
分かっていて書いているならば別にいいと思うんですが、以下のことを思います。
https://www.ms.u-tokyo.ac.jp/~yasuyuki/sem.htm
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.
ちゃんとわかって説明できるかと、読む能力との関係が深いことが初耳でした。説明できないのは、頭の中でコードがちゃんと動くことをシミュレーションできないと言うことで、それは読めてない、と言うことでしょうか。
確かに最初にこれを覚えたときはそのままとりあえず書き方を丸暗記していて、よくわかっていなかったかもしれません。