Conversation
| - 右側(end)により小さい値があれば、左側を捨てる。 nums.last() < nums[middle] then start = middle + 1 // middleを探索範囲外にする。 | ||
|
|
||
| 所感 | ||
| - nums.last()との比較でかなり面食らう感じがある。nums.last()は最大値、最小値、その他の値のどれでもあるのになぜ比較しているのか?と初見で思った。 |
There was a problem hiding this comment.
最小値のことを、値がnums.last()以下な要素の中で一番左のものと言い換えているから、でしょうか。
There was a problem hiding this comment.
はい。冗長に書くと以下のような理解です。
nums.last()はnums.last()以下な要素の一番大きい値であり、一番右になる。
nums[i] <= nums.last() としているので、nums[i]はnums.last()以下な要素の中で一番左のものになる。
middleが切り捨てになっていて単調減少していくのでiも左に寄っていく。
There was a problem hiding this comment.
以下はfyiの説明です。
回転済みの配列は「左の大きい昇順区間」と「右の小さい昇順区間」に分かれて、そのときnums.last()は必ず右区間の要素になります。
なので nums[i] <= nums.last() は「i が右区間に属するか?」の判定になって、左では False、右では True の単調述語(FF…FFTT…TT)になります。探索中は(FF...F??...??T...TT)のような感じですね。
あとは、この境界部分にまつわる不変条件をstart, endに対して考え、初期化と更新式を考えたらいいですね。step2aの実装では、startは一番左の?(一番右のFの右隣)、endは一番左のTと考えてると言えます。
初期状態は(???...???)なので、start = 0, end = nums.len()の初期化です。
ピボットmiddleから情報を取り、nums[middle] <= nums.last()、つまりmiddle番目がTならend = middleと更新します。
そうでないならmiddle番目はFなので、start = middle + 1と更新します。
やがて?がなくなり、(FF…FFTT…TT)と全て確定します。知りたいのはTの一番左なので、停止時のendを使って答えはnums[end]です。または、一番右のFの右隣と考えてnums[start]でもいいです。このときstart == endなので、ループ継続条件はstart < endで良いですね。
| 所感 | ||
| - nums.last()との比較でかなり面食らう感じがある。nums.last()は最大値、最小値、その他の値のどれでもあるのになぜ比較しているのか?と初見で思った。 | ||
| 自分には認知負荷が高い。 | ||
| (start,end]な半開区間も実装しようかと思ったが時間切れなのでスキップ。 |
There was a problem hiding this comment.
問題: 153. Find Minimum in Rotated Sorted Array
次に解く問題: 33. Search in Rotated Sorted Array
ファイルの構成:
./src/bin/<各ステップ>.rs