From e6b7ed406a97d25a2d2c1dbe2445c7fe2170ff34 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Wed, 1 Apr 2026 08:00:15 +0900 Subject: [PATCH 1/4] 33. Search in Rotated Sorted Array --- 33/memo.md | 20 ++++++++++++++++++++ 33/sol1.py | 32 ++++++++++++++++++++++++++++++++ 33/sol2.py | 24 ++++++++++++++++++++++++ 33/sol3.py | 17 +++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 33/memo.md create mode 100644 33/sol1.py create mode 100644 33/sol2.py create mode 100644 33/sol3.py diff --git a/33/memo.md b/33/memo.md new file mode 100644 index 0000000..a03192b --- /dev/null +++ b/33/memo.md @@ -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 + + diff --git a/33/sol1.py b/33/sol1.py new file mode 100644 index 0000000..6237192 --- /dev/null +++ b/33/sol1.py @@ -0,0 +1,32 @@ +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 + + possible_target_index = (left_in_sorted + minimum_index) % len_nums + return possible_target_index if nums[possible_target_index] == target else -1 diff --git a/33/sol2.py b/33/sol2.py new file mode 100644 index 0000000..ba29928 --- /dev/null +++ b/33/sol2.py @@ -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 diff --git a/33/sol3.py b/33/sol3.py new file mode 100644 index 0000000..9ab9621 --- /dev/null +++ b/33/sol3.py @@ -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 From ce8de4d25523c9e4a22c72b625c45780b3603ec1 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Sat, 4 Apr 2026 19:32:49 +0900 Subject: [PATCH 2/4] Add suggested changes --- 33/sol1.py | 20 +++++++++----------- 33/sol1_revised.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 33/sol1_revised.py diff --git a/33/sol1.py b/33/sol1.py index 6237192..41c5a17 100644 --- a/33/sol1.py +++ b/33/sol1.py @@ -17,16 +17,14 @@ def search(self, nums: list[int], target: int) -> int: 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 + left = 0 # (i - minimum_index) % len_nums < left -> nums[i] < target + right = len_nums # (i - minimum_index) % len_nums >= right -> nums[i] >= target + while left < right: + mid = left + (right - left) // 2 + if nums[(mid + minimum_index) % len_nums] < target: + left = mid + 1 else: - right_in_sorted = mid_in_sorted + right = mid - possible_target_index = (left_in_sorted + minimum_index) % len_nums - return possible_target_index if nums[possible_target_index] == target else -1 + target_index = (left + minimum_index) % len_nums + return target_index if nums[target_index] == target else -1 diff --git a/33/sol1_revised.py b/33/sol1_revised.py new file mode 100644 index 0000000..41c5a17 --- /dev/null +++ b/33/sol1_revised.py @@ -0,0 +1,30 @@ +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 = 0 # (i - minimum_index) % len_nums < left -> nums[i] < target + right = len_nums # (i - minimum_index) % len_nums >= right -> nums[i] >= target + while left < right: + mid = left + (right - left) // 2 + if nums[(mid + minimum_index) % len_nums] < target: + left = mid + 1 + else: + right = mid + + target_index = (left + minimum_index) % len_nums + return target_index if nums[target_index] == target else -1 From 4d130878bd05535b69d4ee52676247d0fb88d73d Mon Sep 17 00:00:00 2001 From: tom4649 Date: Sat, 4 Apr 2026 20:23:37 +0900 Subject: [PATCH 3/4] Fix --- 33/sol1.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/33/sol1.py b/33/sol1.py index 41c5a17..498e472 100644 --- a/33/sol1.py +++ b/33/sol1.py @@ -17,14 +17,17 @@ def search(self, nums: list[int], target: int) -> int: minimum_index = left # Step 2: Find the target - left = 0 # (i - minimum_index) % len_nums < left -> nums[i] < target - right = len_nums # (i - minimum_index) % len_nums >= right -> nums[i] >= target - while left < right: - mid = left + (right - left) // 2 - if nums[(mid + minimum_index) % len_nums] < target: - left = mid + 1 + 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 = mid + right_in_sorted = mid_in_sorted - target_index = (left + minimum_index) % len_nums - return target_index if nums[target_index] == target else -1 + if nums[(left_in_sorted + minimum_index) % len_nums] != target: + return -1 + return (left_in_sorted + minimum_index) % len_nums From e2ba38832ca2f96581ddf68aa1c6c97a5c3734f8 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Sun, 5 Apr 2026 06:19:26 +0900 Subject: [PATCH 4/4] Add suggested changes --- 33/sol1_revised.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/33/sol1_revised.py b/33/sol1_revised.py index 41c5a17..a764885 100644 --- a/33/sol1_revised.py +++ b/33/sol1_revised.py @@ -17,14 +17,19 @@ def search(self, nums: list[int], target: int) -> int: minimum_index = left # Step 2: Find the target - left = 0 # (i - minimum_index) % len_nums < left -> nums[i] < target - right = len_nums # (i - minimum_index) % len_nums >= right -> nums[i] >= 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 + minimum_index) % len_nums] < target: + if nums[mid] < target: left = mid + 1 else: right = mid - - target_index = (left + minimum_index) % len_nums - return target_index if nums[target_index] == target else -1 + return left if nums[left] == target else -1