-
Notifications
You must be signed in to change notification settings - Fork 0
33. Search in Rotated Sorted Array #38
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,58 @@ | ||
| # step1 何も見ずに解く | ||
| - 求めたいもの | ||
| - targetの候補になるものを求める。最後にtargetと一致するかどうかをチェックする。 | ||
| - どうやって範囲を狭めていくか | ||
| - leftより左はtargetではない | ||
| - rightより右はtargetではない | ||
| - 終了条件 | ||
| - left == rightとなると、rightまたはleftが答えの候補になる | ||
| - 作業 | ||
| - 中央のインデックスはmiddle = (left + right) / 2とする(切り捨て) | ||
| - 範囲の更新は以下でないと無限ループになる | ||
| - left = middle + 1 | ||
| - right = middle | ||
| - middleを含む右が昇順の時 | ||
| - targetが(middle + 1)の値以上rightの値以下の時 | ||
| - middleを含む左にtargetは存在しないのでleft = middle + 1に更新できる | ||
| - targetが(middle + 1)の値より小さい or rightの値より大きい時 | ||
| - middleより右にtargetは存在しないのでright = middleに更新できる | ||
| - ※ 「targetがmiddleの値以上rightの値以下の時」としていないのは、leftの更新によって範囲を1以上狭められないパターンが出るため | ||
| - middleを含む左が昇順の時 | ||
| - targetがleftの値以上middleの値以下の時 | ||
| - middleより左にtargetが存在しないのでright = middleに更新できる | ||
| - targetがleftより小さい or middleより大きい時 | ||
| - middleを含む左にはtargetは存在しないのでleft = middle + 1で更新できる | ||
|
|
||
| 考え方的に間違ってない気がするが、考えるのに疲れる… | ||
|
|
||
| 時間計算量はO(logN)で、空間計算量はO(1) | ||
| numsの最大サイズは10^4なので余裕で1秒以内に間に合う | ||
|
|
||
| ```ruby | ||
| # @param {Integer[]} nums | ||
| # @param {Integer} target | ||
| # @return {Integer} | ||
| def search(nums, target) | ||
| left = 0 | ||
| right = nums.size - 1 | ||
| while left < right | ||
| mid = (left + right) / 2 | ||
| if nums[mid] <= nums[right] | ||
| if nums[mid + 1] <= target && target <= nums[right] | ||
| left = mid + 1 | ||
| else | ||
| right = mid | ||
| end | ||
| else | ||
| if nums[left] <= target && target <= nums[mid] | ||
| right = mid | ||
| else | ||
| left = mid + 1 | ||
| end | ||
| end | ||
| end | ||
| not_existed = -1 | ||
| nums[left] == target ? left : not_existed | ||
| end | ||
| ``` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # step2 他の方の解答を見る | ||
|
|
||
| ## rotateした場所を見つけて二回二分探索する方法 | ||
| https://github.com/sakupan102/arai60-practice/pull/44 | ||
| これも思いついたが、長くなる割に分割することでわかりやすくなるものでもないのでやめた。 | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # step3 3回続けて10分以内に書いてエラーを出さなければOKとする | ||
|
|
||
| ```ruby | ||
| # @param {Integer[]} nums | ||
| # @param {Integer} target | ||
| # @return {Integer} | ||
| def search(nums, target) | ||
| left = 0 | ||
| right = nums.size - 1 | ||
| while left < right | ||
| mid = (left + right) / 2 | ||
| if nums[mid] <= nums[right] | ||
| if nums[mid + 1] <= target && target <= nums[right] | ||
|
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. if nums[mid] < target && target <= nums[right]
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. コメントありがとうございます。おっしゃる通りですね。 if nums[mid] < target && target <= nums[right]
left = mid + 1 |
||
| left = mid + 1 | ||
| else | ||
| right = mid | ||
| end | ||
| else | ||
| if nums[left] <= target && target <= nums[mid] | ||
| right = mid | ||
| else | ||
| left = mid + 1 | ||
| end | ||
| end | ||
| end | ||
| not_existed = -1 | ||
| nums[left] == target ? left : not_existed | ||
| end | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ## step4 レビューを受けて解答を修正 |
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.
middle の位置が「target より左」「target または target より右」で分類するわけですよね。
なんか「無限ループになるから」は理由として妙な気がしています。
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.
コメントありがとうございます。
おっしゃる通り考え方が不自然だったので、自分なりに理解を以下のように整理しました。
先にleftやrightの更新方法が決まった後に、「middleをどう決めると毎回範囲を狭めることができるか?」と考えるのが自然ですね。
middleが
middleを切り捨てで決めるとどちらの場合でも範囲を1絞ることができる
一方で、以下の分類もできる。
middleが
middleを切り上げで決めるとどちらの場合でも範囲を1絞ることができる