diff --git a/35. Search Insert Position.md b/35. Search Insert Position.md new file mode 100644 index 0000000..1caf72b --- /dev/null +++ b/35. Search Insert Position.md @@ -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 +``` + diff --git a/java.md b/java.md new file mode 100644 index 0000000..9b0e9bd --- /dev/null +++ b/java.md @@ -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; + } +} +```