Create 35. Search Insert Position.md#41
Conversation
| left = search_insert_helper(start_index, mid) | ||
| right = search_insert_helper(mid+1, end_index) |
| return low | ||
| ``` | ||
|
|
||
| もう何問か二分探索の問題があるので、読むのには不安が残るが先に進む。 |
There was a problem hiding this comment.
分かっているのかいないのか、分からないなと思いましたが、まあ、ゆっくりと分かればいいです。
シフト制の職場で、ループのたびに働いている人が変わる、つまり引き継いでいると思ってください。
おかしな値がでると「誰の責任か」が追求される、このギスギスしている職場の話を読んでください。
https://discord.com/channels/1084280443945353267/1237649827240742942/1344639504233005137
意思疎通ができていない場合、たとえば、9人目は「5が答えだったじゃないか」といって怒り、8人目は「5が答えでないなんて言ってないぞ」と怒りますね。つまり、left の意味について意思疎通ができていません。
これが起きないように left と right がどういう意味なのかを書けますか。
There was a problem hiding this comment.
正直理解しきれていないと思います。
leftとrightの意味、、、あまり論点がわかりませんが、書きます。
この関数は条件を満たすものの左側を探します。
target <= nums[right] ではありますが、nums[left] <= targetは必ず成り立つわけではないです。
left は「条件を満たす可能性のあるindexの最小」
right は「条件を満たさないことが判明しているindexの最小」
です。
すみません、意味を上手く言葉にできないので違和感あれば教えてください。
[1,3,5,6]、target=4だとすると、[o1o3o5o6o] oのどこかに値が入ります。
①left=0, right=4として、(right=3とすると一番右側のoを探索できない)
nums[2]=5 > targetなので、right=2となり、
次は[o1o3o5]を探索します。
②left=0, right=2でnums[1] =3 < targetなので、 left=1となり、
次は[o3o5]を探索します。
③left=1,right=2で nums[1]=3 < targetなのでleft=2となり、
次は[o5]を探索します
④left=2,right=2で、left < rightではないのでループを終了する。
答えはleft=2
There was a problem hiding this comment.
うーん。
まず、たとえば、[1, 1, 3, 3, 5, 5, 7, 7] で target が 3 だったら 2 が答えなんですよね。
シフトに入っているとして、left = 10, right = 20, target = 100 といわれたとしましょう。
ここで、ボスから緊急の指令が入りました。ここまでの前任者の中に仕事をちゃんとやっていないやつがいるらしい。
ついては、もう全部開けて調べてもよい。何が分かったら前任者の不正の証拠だという報告をしますか。
たとえば、40を調べたら1000だった、というのは不正の証拠ではないですね。
There was a problem hiding this comment.
left は「条件を満たす可能性のあるindexの最小」
right は「条件を満たさないことが判明しているindexの最小」
なので、
9を開けて100より大きいか、20を開けて100より小さければ不正の証拠になるとおもいます。
There was a problem hiding this comment.
なるほど、9を開けて100だったらどうですか?
一応、あとなんか頭の中で複雑な式変形をしているように見受けられるのですが、そこを言語化できますか?
There was a problem hiding this comment.
等号とか大丈夫ですか?
ちょっと具体的な例をいくつか作ってやってみたほうがいいと思います。
つまり、何を保証して次の人に引き継いでいるんでしょうか。
えーっと、つまり、保証している内容というのは「先頭から left -1 まで(両端含む?)をすべて開けたときに、それはすべて、なんとか」なんですか。そして、「right から最後まで(両端を含む?)をすべて開けたときに、それはすべて、なんとか」なんですか。
あと、ソースコードの前任者がしたこととの関係を説明できますか。
There was a problem hiding this comment.
すみません間違っていました。
保障されていてほしい条件はleft-1 < target <= rightで
不正と判定できる条件は left-1 >= target, right < targetです。
(意味を書きます)
探しているものはtarget以上の最小のIndexです。
leftはtargetより大きいかもしれない最小のIndex
(left-1はtargetより小さいことが分かっている最大のIndex)
rightはtargetより大きいことが分かっている最小のindex
ループの人の立場になると、left, rightが与えられたとして、そのmidを開けてそれがtargetより小さければ、それは答えにはならずより右側にあることがわかるので、leftをmid+1として、次の人に引き継ぎます。
midがtarget以上であれば、答えになり得るので、right=midとして、より左側の答えを探します。
先頭からleft-1まではすべてtargetより小さく、
rightから最後まではすべてtarget以上です。
There was a problem hiding this comment.
前任者との関係ですが、質問の意図がくみ取れていないのですが、こういうことでしょうか。
仕事を複数人で行います。
left, rightの両端を含む範囲で条件を満たす最小のものを探したいです。
範囲を渡されたら、その中心の箱を開けて条件を満たすか確かめます。
条件を満たしていないならその箱より右側にあることを次の人に引き継ぎます。
条件を満たしているならその箱よりも大きいものは最小にはならないので見なくてよいことを次の人に引き継ぎます。
There was a problem hiding this comment.
あ、前任者との関係は、「ループの人の立場になると」というところで書かれていることなので、それで大丈夫です。
あとは、必ず範囲が狭くなっていくこととループを抜けたときに欲しいものがでてきていれば動きますね。
There was a problem hiding this comment.
ありがとうございます。
おかげさまで二分探索の気持ちがわかってきました。
| insert_position ならば、答えは、0 <= position <= nums.size() ですよね。 | ||
|
|
||
| だから、これは閉区間といえば閉区間なのです。つまり、「何が」を分かっていないで、開区間で閉区間でと書いても仕方がないでしょう。 | ||
| ``` |
There was a problem hiding this comment.
自分にとっては「閉区間」「開区間」という言葉を使わなくても
「左側、つまり、条件を満たさないことが判明している左側の最大の場所」か
「左側、つまり、条件を満たさないことが判明していない左側の最小の場所」
olsen-blue/Arai60#42 (comment)
と理解することがわかりやすかったです。
There was a problem hiding this comment.
こう捉えるとstep3のコードの終了条件はlow, つまり「条件を満たさないことが判明していない左側の最小の場所」とhigh, つまり「条件を満たすことが判明している右側の最小の場所」が出会うところなのでreturn highの方が自然な気がしてきました。
There was a problem hiding this comment.
いつもレビューありがとうございます!
「左側、つまり、条件を満たさないことが判明している左側の最大の場所」か
「左側、つまり、条件を満たさないことが判明していない左側の最小の場所」
私もこの理解になりました。
開区間、閉区間は何を意味するかが分かりにくいので、使わないほうがよさそうだと感じました。
There was a problem hiding this comment.
おっしゃる通りreturn highのほうが自然ですね。
https://leetcode.com/problems/search-insert-position/description/