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
20 changes: 20 additions & 0 deletions 33/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 33. Search in Rotated Sorted Array

- 前二問(ソート+循環済み配列の最小値インデックス、単純なtarget探索)に分解できることに気づく
- 練習のためbisectを使わずに書いた
- 二分探索を一回で行う方法はあるのか?

https://discord.com/channels/1084280443945353267/1233295449985650688/1239594872697262121
- 二分探索を一回で行う方法を見つけた。賢すぎる。
- 関数 comp は target との大小で-1, 0, 1の三段階のスコアを振る。しかし循環されているので、これだと昇順にはならない。
- これを解消するためには、循環で本来の位置より前にきた数字のスコアを下げれば良い。最低どのくらい下げれば良いかというと、compの最大値と最小値との差 1-(-1) = 2である。この係数は-2以下であれば何でも良い。
- 自分でも空で書いてみる

https://github.com/hroc135/leetcode/pull/41#discussion_r1970984248
> 見直したら cmp いらなくて

なるほど、Pairにすれば解決するのか。自分で思いつきたかったな

https://github.com/mamo3gr/arai60/blob/33_search-in-rotated-sorted-array/33_search-in-rotated-sorted-array/memo.md


33 changes: 33 additions & 0 deletions 33/sol1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Solution:
def search(self, nums: list[int], target: int) -> int:
if not nums:
return -1
len_nums = len(nums)

# Step 1: Find the minimum value
left = 0 # i < left -> nums[i] > nums[-1]
right = len_nums # i >= right -> nums[i] <= nums[-1]
while left < right:
mid = left + (right - left) // 2
if nums[mid] > nums[-1]:
left = mid + 1
else:
right = mid

minimum_index = left

# Step 2: Find the target
left_in_sorted = (
0 # (i - minimum_index) % len_nums < left_in_sorted -> nums[i] < target
)
right_in_sorted = len_nums # (i - minimum_index) % len_nums >= right_in_sorted -> nums[i] >= target
while left_in_sorted < right_in_sorted:
mid_in_sorted = left_in_sorted + (right_in_sorted - left_in_sorted) // 2
if nums[(mid_in_sorted + minimum_index) % len_nums] < target:
left_in_sorted = mid_in_sorted + 1
else:
right_in_sorted = mid_in_sorted

if nums[(left_in_sorted + minimum_index) % len_nums] != target:
return -1
return (left_in_sorted + minimum_index) % len_nums
35 changes: 35 additions & 0 deletions 33/sol1_revised.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Solution:
def search(self, nums: list[int], target: int) -> int:
if not nums:
return -1
len_nums = len(nums)

# Step 1: Find the minimum value
left = 0 # i < left -> nums[i] > nums[-1]
right = len_nums # i >= right -> nums[i] <= nums[-1]
while left < right:
mid = left + (right - left) // 2
if nums[mid] > nums[-1]:
left = mid + 1
else:
right = mid

minimum_index = left

# Step 2: Find the target
if nums[-1] < target:
left, right = (
0,
minimum_index,
)
else:
left, right = minimum_index, len_nums
# i < left -> nums[i] < target
# i >= right -> nums[i] >= target
while left < right:
mid = left + (right - left) // 2
if nums[mid] < target:
left = mid + 1
else:
right = mid
return left if nums[left] == target else -1
24 changes: 24 additions & 0 deletions 33/sol2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import bisect


class Solution:
def search(self, nums: list[int], target: int) -> int:
if not nums:
return -1
len_nums = len(nums)

# Step 1: Find the minimum value
minimum_index = bisect.bisect_left(
range(len_nums), True, key=lambda x: nums[x] <= nums[-1]
)

# Step 2: Find the target
possible_target_index_in_soted = bisect.bisect_left(
range(len_nums),
True,
key=lambda x: nums[(x + minimum_index) % len_nums] >= target,
)
possible_target_index = (
possible_target_index_in_soted + minimum_index
) % len_nums
return possible_target_index if nums[possible_target_index] == target else -1
17 changes: 17 additions & 0 deletions 33/sol3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import bisect


class Solution:
def search(self, nums: list[int], target: int) -> int:
if not nums:
return -1
len_nums = len(nums)

def comp(a, b):
return (a < b) - (a > b)

def priority(x):
return (x > nums[-1]) * -2 + comp(target, x)

possible_index = bisect.bisect_left(nums, priority(target), key=priority)
return possible_index if nums[possible_index] == target else -1