35. Search Insert Position#39
Conversation
| int right = nums.size(); | ||
|
|
||
| while (left < right) { | ||
| int mid = (left + right) / 2; |
There was a problem hiding this comment.
オーバーフローを避けるため、
int mid = left + (right - left) / 2;と書いたほうが良いと思います。
There was a problem hiding this comment.
承知しました。確かにそちらの方がよさそうです。
|
|
||
| while (left < right) { | ||
| int mid = (left + right) / 2; | ||
| if (nums[mid] == target) { |
There was a problem hiding this comment.
あまり深く考えていなかったのですが、二分探索が終わるとleftとrightの値が同じになるはずなのでこのif文は必要なかったと思います。一応LeetCodeでも確認したところなくても動きました。
There was a problem hiding this comment.
二分探索が終わるとleftとrightの値が同じになる
とありますが、ループ終了後には、どこを指していますか?
There was a problem hiding this comment.
以下のプレイグラウンドで値を見ながら確認したのですが、nums[mid]がtarget以上の場合はright = midに、nums[mid]がtargetより小さい場合はleft = mid + 1になるので最終的にleftとrightは同じ値になって、target以上の最小のnumのインデックスを指しそうです。
https://leetcode.com/playground/mR6MWyoh
また、下記のコードがあることで最終的な答えは変わらないですがnums[mid] == targetの場合は早期にループを抜けられることもわかりました。
if (nums[mid] == target) {
return mid;
}
| auto it = find(nums.begin(), nums.end(), target); | ||
| if (it != nums.end()) { | ||
| return it - nums.begin(); | ||
| } |
There was a problem hiding this comment.
問題文には、
You must write an algorithm with O(log n) runtime complexity.
とありますが、こちらの計算量はどうなっていますか?
lower_boundを一回呼び出すだけで書けますか?
There was a problem hiding this comment.
5ky7さんのPRを参考にlower_bound1回だけで書いてみました。見つからない場合もitがnums.end()になるのでdistanceを取ればちょうどnums.size()と同じになるのでこれだけでよかったです。
https://github.com/5ky7/arai60/pull/41/changes#diff-0c860cd754249868513e4f9054206317fa33d0f548fc3896ac2b3e11822fd852R5
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
auto it = lower_bound(nums.begin(), nums.end(), target);
int position = distance(nums.begin(), it);
return position;
}
};There was a problem hiding this comment.
ぼくの書いた方の計算量ですが、lower_boundの計算量はO(log n)ですがfindの方の計算量はO(n)のようなので問題文の条件をクリアできていなさそうです。
There was a problem hiding this comment.
見つからない場合もitがnums.end()になる
見つからない場合は、いつもそうなりますかね?
There was a problem hiding this comment.
見つからない場合というかtarget以上の要素がない場合、つまりtargetがいちばん後ろにくるべきケースではlower_boundでnums.end()が返ると思うのでこれでいいかなと思いました。
There was a problem hiding this comment.
「(target以上の要素が)見つからない」という意味でしたら、それで合っていますね。
|
|
||
| ### step2 | ||
|
|
||
| 他の方のコード(https://github.com/5ky7/arai60/pull/41/changes#diff-0c860cd754249868513e4f9054206317fa33d0f548fc3896ac2b3e11822fd852R19)を見てみると、lower_bound自体を実装していたので自分も実装してみた。 |
There was a problem hiding this comment.
すみません、何か勘違いしているかもなのですがstep2に載せたコードがlower_boundの実装のつもりでした。
There was a problem hiding this comment.
lower_boundと振る舞いが違うので、ドキュメントを確認してみると良さそうです。
https://en.cppreference.com/cpp/algorithm/lower_bound
この問題:https://leetcode.com/problems/search-insert-position/description/
次に解く問題:https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/description/