From 11099928cfae655d99c5fce5210dc3364a496d2b Mon Sep 17 00:00:00 2001 From: seal_azarashi Date: Fri, 8 Nov 2024 08:39:07 +0900 Subject: [PATCH 1/3] step 1 - 3 --- .../Binary_Search/search-insert-position.md | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 arai60/Binary_Search/search-insert-position.md diff --git a/arai60/Binary_Search/search-insert-position.md b/arai60/Binary_Search/search-insert-position.md new file mode 100644 index 0000000..29294b6 --- /dev/null +++ b/arai60/Binary_Search/search-insert-position.md @@ -0,0 +1,119 @@ +# 35. Search Insert Position + +LeetCode URL: https://leetcode.com/problems/search-insert-position/description/ + +この問題は Java で解いています。 +各解法において、メソッドが属するクラスとして `Solution` を定義していますが、これは Java の言語仕様に従い、コードを実行可能にするために必要なものです。このクラス自体には特定の意味はなく、単にメソッドを組織化し、実行可能にするためのものです。 + +## Step 1 + +Binary search を実施して値が見つからなかった場合、while 文を抜けた時点で left ポインタが探索対象の値の次に大きい値を指すことを理解し、次のように書いた。好みで閉区間にしている。 + +```java +/** + * 時間計算量: O(log n) + * 空間計算量: O(1) + */ +class Solution { + public int searchInsert(int[] nums, int target) { + int left = 0, right = nums.length - 1; + while (left <= right) { + int middle = left + (right - left) / 2; + if (nums[middle] == target) { + return middle; + } + if (nums[middle] < target) { + left = middle + 1; + } + if (target < nums[middle]) { + right = middle - 1; + } + } + return left; + } +} +``` + +## Step 2 + +### 半開区間 (左閉右開) の実装 + +半開区間でも書いてみる。こちらの方が一般的な印象があるので以後はこちらをベースに書いていく。 + +```java +/** + * 時間計算量: O(log n) + * 空間計算量: O(1) + */ +class Solution { + public int searchInsert(int[] nums, int target) { + int left = 0, right = nums.length; + while (left < right) { + int middle = left + (right - left) / 2; + if (nums[middle] == target) { + return middle; + } + if (nums[middle] < target) { + left = middle + 1; + } else { + right = middle; + } + } + return left; + } +} +``` + +### 必ず while 文を抜ける実装 + +途中で処理を中断せず while 文を抜けた場合、その時点で left ポインタは探索対象、もしくはその次に大きい値を指している。これを踏まえて step 1 の処理を、必ず while 文を抜けるように修正してみる。 + +"return the index if the target is found" とある問題文の指示を反映している感が薄まったような印象。 +一方、どの実装についても内容の理解には上記の left ポインタの特徴を把握することが避けられないのを考えると、これを把握している読み手ならまあ迷うこともないなずなのでこれでもいいのかなと思った。 + +```java +/** + * 時間計算量: O(log n) + * 空間計算量: O(1) + */ +class Solution { + public int searchInsert(int[] nums, int target) { + int left = 0, right = nums.length; + while (left < right) { + int middle = left + (right - left) / 2; + if (nums[middle] < target) { + left = middle + 1; + } else { + right = middle; + } + } + return left; + } +} +``` + +## Step 3 + +必ず while 文を抜ける実装を採用。 + +```java +/** + * 解いた時間: 2分未満 + * 時間計算量: O(log n) + * 空間計算量: O(1) + */ +class Solution { + public int searchInsert(int[] nums, int target) { + int left = 0, right = nums.length; + while (left < right) { + int middle = left + (right - left) / 2; + if (nums[middle] < target) { + left = middle + 1; + } else { + right = middle; + } + } + return left; + } +} +``` From 4ab989566c109e3379565dff7847ed058a92a05d Mon Sep 17 00:00:00 2001 From: seal_azarashi Date: Fri, 8 Nov 2024 11:19:54 +0900 Subject: [PATCH 2/3] step 4 --- .../Binary_Search/search-insert-position.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arai60/Binary_Search/search-insert-position.md b/arai60/Binary_Search/search-insert-position.md index 29294b6..5e73eee 100644 --- a/arai60/Binary_Search/search-insert-position.md +++ b/arai60/Binary_Search/search-insert-position.md @@ -117,3 +117,26 @@ class Solution { } } ``` + +## Step 4 + +### Arrays クラスを用いる解法 + +ahayashi さんの指摘で Arrays.binarySearch() があったことを思い出したので加筆。 + +```java +/** + * 時間計算量: O(log n) + * 空間計算量: O(1) + */ +class Solution { + public int searchInsert(int[] nums, int target) { + int foundIndex = Arrays.binarySearch(nums, target); + if (0 < foundIndex) { + return foundIndex; + } + + return -(foundIndex + 1); + } +} +``` From 7975e7aa22d86f044dc6f2a097bd3b2348f6b900 Mon Sep 17 00:00:00 2001 From: seal_azarashi Date: Mon, 11 Nov 2024 07:56:03 +0900 Subject: [PATCH 3/3] add step 4 --- arai60/Binary_Search/search-insert-position.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arai60/Binary_Search/search-insert-position.md b/arai60/Binary_Search/search-insert-position.md index 5e73eee..1abad37 100644 --- a/arai60/Binary_Search/search-insert-position.md +++ b/arai60/Binary_Search/search-insert-position.md @@ -132,7 +132,7 @@ ahayashi さんの指摘で Arrays.binarySearch() があったことを思い出 class Solution { public int searchInsert(int[] nums, int target) { int foundIndex = Arrays.binarySearch(nums, target); - if (0 < foundIndex) { + if (0 <= foundIndex) { return foundIndex; } @@ -140,3 +140,14 @@ class Solution { } } ``` + +その後 [oda さんの指摘](https://github.com/seal-azarashi/leetcode/pull/38#discussion_r1834834703)を受けビット反転するよう修正。 + +```java +class Solution { + public int searchInsert(int[] nums, int target) { + int foundIndex = Arrays.binarySearch(nums, target); + return 0 <= foundIndex ? foundIndex : ~foundIndex; + } +} +```