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
95 changes: 95 additions & 0 deletions 35. Search Insert Position.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
二分探索。

1st

target以上の値になる位置を求める。それがinsert position。
pythonではオーバーフローを考慮しなくて良いが、考慮する必要がある言語だと mid = left + (right - left) // 2のようにする。
```python
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] >= target:
right = mid
else:
left = mid + 1
return left
```

> コードはいいと思います。
これ、どう考えるといいかなあと思っています。
n 個要素があると、植木算で n + 1 個の切れ目がありますね。
そのうち、どこで切ると、
右はすべて、target <= nums[i] で、
左はすべて、nums[i] < target となるか、ということですね。
これを answer とでもしましょう。
だから、left と right は実は閉区間で、一致するまで回さないといけませんね。
mid = (left + right) // 2
とすると、切り捨てられるので、
left <= mid < right
になります。
nums[mid] < target
が判明すると、
mid < answer が分かります。
一方、
target <= nums[mid]
が判明すると、
answer <= mid
が分かりますね。

2nd
bisectモジュール。
bisect_leftの実装はここ。https://github.com/python/cpython/blob/cfbdce72083fca791947cbb18114115c90738d99/Lib/bisect.py#L74
Pythonで実装されていて特に変なことはしてない。
```python
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
return bisect.bisect_left(nums, target)
```

`[:i]`についてtargetより小さく、`[i:]`についてtarget以上になるiを求める。
```python
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
low, high = 0, len(nums)
while low < high:
mid = (low + high) // 2
if nums[mid] < target:
low = mid + 1
else:
high = mid
return low
```

3rd

```python
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
else:
right = mid
return left
```

4th

```python
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
low = 0
high = len(nums)
while low < high:
middle = (low + high) // 2
if nums[middle] < target:
low = middle + 1
else:
high = middle
return low
```

35 changes: 35 additions & 0 deletions java.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
`Arrays.binarySearch`を使った解法。
keyが存在しない場合は`- (insertion point) - 1`が返るようになっていて、マイナス値であることが保証されている。
Pythonの`bisect`モジュールのように素直にinsertion pointを返す実装とどっちが良いかはケースバイケースか。


https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#binarySearch-int:A-int-

```java
class Solution {
public int searchInsert(int[] nums, int target) {
int ip = Arrays.binarySearch(nums, target);
if (ip >= 0) {
return ip;
}
return -ip - 1;
}
}
```

ビット反転で良い。
2の補数 -> ビット反転をして1を足す

ipをマイナスして、1を引く
-> ipの2の補数を求めて、1を引く
-> ipのビット反転をして、1を足して、1を引く
-> ipのビット反転をする

```java
class Solution {
public int searchInsert(int[] nums, int target) {
int ip = Arrays.binarySearch(nums, target);
return ip >= 0 ? ip : ~ip;
}
}
```