Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions 33/step1.md
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
Comment on lines +11 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

middle の位置が「target より左」「target または target より右」で分類するわけですよね。

なんか「無限ループになるから」は理由として妙な気がしています。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントありがとうございます。
おっしゃる通り考え方が不自然だったので、自分なりに理解を以下のように整理しました。

先にleftやrightの更新方法が決まった後に、「middleをどう決めると毎回範囲を狭めることができるか?」と考えるのが自然ですね。

middleが

  • targetより左
    • leftより左にはtargetがないのでleft = middle + 1に範囲を絞ることができる
  • targetまたはtargetより右
    • rightより右にtargetがないのでright = middleに範囲を絞ることができる

middleを切り捨てで決めるとどちらの場合でも範囲を1絞ることができる

一方で、以下の分類もできる。
middleが

  • targetまたはtargetより左
    • leftより左にtargetがないのでleft = middleに範囲を絞ることができる
  • targetより右
    • rightより右にtargetがないのでright = middle - 1に範囲を絞ることができる

middleを切り上げで決めるとどちらの場合でも範囲を1絞ることができる

- 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
```

6 changes: 6 additions & 0 deletions 33/step2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# step2 他の方の解答を見る

## rotateした場所を見つけて二回二分探索する方法
https://github.com/sakupan102/arai60-practice/pull/44
これも思いついたが、長くなる割に分割することでわかりやすくなるものでもないのでやめた。

29 changes: 29 additions & 0 deletions 33/step3.md
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]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if nums[mid] < target && target <= nums[right]
の方が自然かなと思いました。mid の位置が target 未満と確定する場合、left は mid + 1 で更新するということです。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントありがとうございます。おっしゃる通りですね。
odaさんにもコメントいただきましたが、midがtargetより左/targetあるいはtargetより右で分類しているので、targetより左だと確定した時にleft = mid + 1とする方が自然ですね。

            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
```
1 change: 1 addition & 0 deletions 33/step4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## step4 レビューを受けて解答を修正