-
Notifications
You must be signed in to change notification settings - Fork 0
Solved Arai60/35. Search Insert Position #41
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,132 @@ | ||
## Step 1. Initial Solution | ||
|
||
- bisect.bisect_leftで答えは得られる | ||
- 自分でこれを実装する | ||
- begin, endの定義は他にもやりようがある | ||
- ここでは[begin, end)で定義している | ||
- begin-1より大きく、endより小さい位置にある | ||
- begin == endになったらその位置に入れてあげれば良い | ||
|
||
```python | ||
class Solution: | ||
def searchInsert(self, nums: List[int], target: int) -> int: | ||
def binary_search(begin: int, end: int) -> int: | ||
middle = (begin + end) // 2 | ||
if begin == end or target == nums[middle]: | ||
return middle | ||
if target < nums[middle]: | ||
return binary_search(begin, middle) | ||
if target > nums[middle]: | ||
return binary_search(middle + 1, end) | ||
return binary_search(0, len(nums)) | ||
``` | ||
|
||
### Complexity Analysis | ||
|
||
- 時間計算量:O(log n) | ||
- 空間計算量:O(1) | ||
|
||
## Step 2. Alternatives | ||
|
||
- 他にも書き方を試してみる | ||
- target == nums[middle]をなくす | ||
|
||
```python | ||
class Solution: | ||
def searchInsert(self, nums: List[int], target: int) -> int: | ||
def binary_search(begin: int, end: int) -> int: | ||
middle = (begin + end) // 2 | ||
if begin == end: | ||
return middle | ||
if target <= nums[middle]: | ||
return binary_search(begin, middle) | ||
else: | ||
return binary_search(middle + 1, end) | ||
return binary_search(0, len(nums)) | ||
``` | ||
|
||
- iterationで解く | ||
|
||
```python | ||
class Solution: | ||
def searchInsert(self, nums: List[int], target: int) -> int: | ||
begin = 0 | ||
end = len(nums) | ||
while begin < end: | ||
middle = (begin + end) // 2 | ||
if target <= nums[middle]: | ||
end = middle | ||
else: | ||
begin = middle + 1 | ||
return begin | ||
``` | ||
|
||
- 確かにleft, rightの方が良く見かけるのを思い出した | ||
- https://github.com/tokuhirat/LeetCode/pull/41/files#diff-2b5524d310a8ba9fe7670e916be44468c8caec3d8aee64536cda8aa952db07f6R46 | ||
|
||
> pythonではオーバーフローを考慮しなくて良いが、考慮する必要がある言語だと mid = left + (right - left) // 2のようにする。 | ||
> | ||
- https://github.com/hayashi-ay/leetcode/pull/40/files | ||
- これも前にやった気がする | ||
- Pythonのint → Cのlong, Pythonのfloat → Cのdouble | ||
|
||
```python | ||
import sys | ||
|
||
i = sys.maxsize | ||
print(i) | ||
# 9223372036854775807 | ||
print(i == i + 1) | ||
# False | ||
i += 1 | ||
print(i) | ||
# 9223372036854775808 | ||
|
||
f = sys.float_info.max | ||
print(f) | ||
# 1.7976931348623157e+308 | ||
print(f == f + 1) | ||
# True | ||
f += 1 | ||
print(f) | ||
# 1.7976931348623157e+308 | ||
``` | ||
|
||
- 今回は一つ一つの数字はユニークだが、連続する場合に前に入れようと思うとtarget == nums[middle]は要注意 | ||
- https://github.com/olsen-blue/Arai60/pull/41/files#diff-912c29ce0f491ca88b1474ced97db89f2d33a36a34cd0f516f5b523e400af176R67 | ||
|
||
## Step 3. Final Solution | ||
|
||
- 閉区間 | ||
|
||
```python | ||
class Solution: | ||
def searchInsert(self, nums: List[int], target: int) -> int: | ||
left = 0 | ||
right = len(nums) - 1 | ||
while left <= right: | ||
middle = (left + right) // 2 | ||
if target <= nums[middle]: | ||
right = middle - 1 | ||
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. right = middleのほうが個人的には良いと思いました。(target <= nums[middle]であってもmiddleが答えになりえるので) |
||
else: | ||
left = middle + 1 | ||
return left | ||
``` | ||
|
||
- 開区間 | ||
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. 個人的には、開区間か閉区間の選択ではなく、leftとrightがそれぞれ何を満たして欲しいものとして考えるかから始めることが重要な気がしています。 以下の方式であれば、 |
||
|
||
```python | ||
class Solution: | ||
def searchInsert(self, nums: List[int], target: int) -> int: | ||
left = -1 | ||
right = len(nums) | ||
while left + 1 < right: | ||
middle = (left + right) // 2 | ||
if target <= nums[middle]: | ||
right = middle | ||
else: | ||
left = middle | ||
return right | ||
``` | ||
|
||
- 反対側の半開区間(-1, len(nums)-1]だけよく分からなかった |
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.
関数名には、どのような値が返ってくるかを表す名前を付けたほうが、ソースコードが理解しやすくなると思います。