From ef9c9a9721e55fee0cda432c7e9d09c34530689d Mon Sep 17 00:00:00 2001 From: takuyasakamoto Date: Thu, 17 Apr 2025 16:44:20 +0900 Subject: [PATCH 1/4] 153. Find Minimum in Rotated Sorted Array --- .../memo.md | 54 +++++++++++++++++++ .../step1.c | 16 ++++++ .../step2.c | 16 ++++++ .../step3.c | 29 ++++++++++ 4 files changed, 115 insertions(+) create mode 100644 leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md create mode 100644 leetcode60/153. Find Minimum in Rotated Sorted Array/step1.c create mode 100644 leetcode60/153. Find Minimum in Rotated Sorted Array/step2.c create mode 100644 leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md b/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md new file mode 100644 index 0000000..098c6f7 --- /dev/null +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md @@ -0,0 +1,54 @@ + +# step1 + +40分かかった。 +時間計算量:O(log(n)) +空間計算量:O(1) +閉区間で行くか半開区間で行くか、前もって決めれば、midの動かし方で躊躇しなくなった。 +midとの比較対象として、ずっと配列の左端の値(target)を使っているが、ベストかわからない。 +もっとスマートな方法があるのだろうか? + +# step2 + +最初にtargetとして、左端の値をとり、midがtargetより小さくなるたびにtargetをmidで更新すれば、targetが最終的な答えにできる。 +leetcodeの答えを見てみたが、全くrotateされていないケースについては、エッジケースとして先に処理し、 +残りのケースの最小値を以下の判定式で求めている。 + +```c:example.c + // If the mid element is greater than its next element then mid+1 + // element is the smallest This point would be the point of change. From + // higher to lower value. + if (nums[mid] > nums[mid + 1]) { + return nums[mid + 1]; + } + + // If the mid element is lesser than its previous element then mid + // element is the smallest + if (mid > 0 && nums[mid - 1] > nums[mid]) { + return nums[mid]; + } +``` + +rotateしていないケースは特殊なので、こっちの方が直感的で分かりやすい可能性もある。 +また、上記の条件式で最初にinflection pointを検出していることで、[2,1]などのケースにおいてもエラーが発生しない。 +上記の条件式での検出を行わない場合、以下の操作をすると、nums[mid] <= nums[0]の条件でright = mid - 1を実行するので、1がnums[0]と比較されずスキップされてしまうのである。 + +```c:example.c + if (nums[mid] > nums[0]) { + left = mid + 1; + } else { + // If nums[0] is greater than the mid value then this means the + // smallest value is somewhere to the left + right = mid - 1; + } +``` + +また、他の人の回答も見てみた。 +while (left < right - 1)という条件で、leftとrightが並ぶ形で終了するケースもあるのだ学んだ。 +色々やると疲れて続かないので、基本的な半開区間、閉区間で練習しようと思う。 + +# step3 + +半開区間、閉区間それぞれ2回ずつ行った。 +エッジケースをそれぞれ手元で書きながら確認しないと厳しい。 +何もせずに書けはするが、脳死で書くだけなので内容を把握したことにはならなそう。 diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/step1.c b/leetcode60/153. Find Minimum in Rotated Sorted Array/step1.c new file mode 100644 index 0000000..3d1239c --- /dev/null +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/step1.c @@ -0,0 +1,16 @@ +int findMin(int* nums, int numsSize) { + int left = 0, right = numsSize - 1, target = nums[0], min = nums[0]; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] < min) { + min = nums[mid]; + } + if (nums[mid] < target) { + right = mid - 1; + } + else { + left = mid + 1; + } + } + return min; +} diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/step2.c b/leetcode60/153. Find Minimum in Rotated Sorted Array/step2.c new file mode 100644 index 0000000..196b185 --- /dev/null +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/step2.c @@ -0,0 +1,16 @@ +int findMin(int* nums, int numsSize) { + int left = 0, right = numsSize - 1, target = nums[0]; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] < target) { + right = mid - 1; + } + else { + left = mid + 1; + } + if (nums[mid] < target) { + target = nums[mid]; + } + } + return target; +} diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c b/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c new file mode 100644 index 0000000..c3c61bc --- /dev/null +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c @@ -0,0 +1,29 @@ +int findMin(int* nums, int numsSize) { + int left = 0, right = numsSize - 1, target = nums[0]; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] < target) { + right = mid - 1; + target = nums[mid]; + } + else { + left = mid + 1; + } + } + return target; +} + +int findMin(int* nums, int numsSize) { + int left = 0, right = numsSize - 1, target = nums[0]; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] < target) { + right = mid - 1; + target = nums[mid]; + } + else { + left = mid + 1; + } + } + return target; +} From 4d43d64770b92bcb504a05b9f78121be8d028208 Mon Sep 17 00:00:00 2001 From: takuyasakamoto Date: Thu, 17 Apr 2025 16:46:24 +0900 Subject: [PATCH 2/4] 153. Find Minimum in Rotated Sorted Array --- leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md | 1 + 1 file changed, 1 insertion(+) diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md b/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md index 098c6f7..b9dfba8 100644 --- a/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md @@ -52,3 +52,4 @@ while (left < right - 1)という条件で、leftとrightが並ぶ形で終了 半開区間、閉区間それぞれ2回ずつ行った。 エッジケースをそれぞれ手元で書きながら確認しないと厳しい。 何もせずに書けはするが、脳死で書くだけなので内容を把握したことにはならなそう。 +トータル3時間かかった。 From 372c9cc7c2c4782bf67200d1eb801c131b7c3338 Mon Sep 17 00:00:00 2001 From: takuyasakamoto Date: Fri, 18 Apr 2025 13:30:47 +0900 Subject: [PATCH 3/4] 153. Find Minimum in Rotated Sorted Array --- .../153. Find Minimum in Rotated Sorted Array/step3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c b/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c index c3c61bc..71f67be 100644 --- a/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/step3.c @@ -14,11 +14,11 @@ int findMin(int* nums, int numsSize) { } int findMin(int* nums, int numsSize) { - int left = 0, right = numsSize - 1, target = nums[0]; - while (left <= right) { + int left = 0, right = numsSize, target = nums[0]; + while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < target) { - right = mid - 1; + right = mid; target = nums[mid]; } else { From f945414760b3c87fd4f14681df9c1283ad1d58b4 Mon Sep 17 00:00:00 2001 From: takuyasakamoto Date: Sat, 19 Apr 2025 00:02:42 +0900 Subject: [PATCH 4/4] final version --- .../final.c | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 leetcode60/153. Find Minimum in Rotated Sorted Array/final.c diff --git a/leetcode60/153. Find Minimum in Rotated Sorted Array/final.c b/leetcode60/153. Find Minimum in Rotated Sorted Array/final.c new file mode 100644 index 0000000..eb9d3d0 --- /dev/null +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/final.c @@ -0,0 +1,32 @@ +int findMin(int* nums, int numsSize) { + int left = 0, right = numsSize - 1; + while (left <= right) { // leftとrightが交差して終了するケース + int mid = left + (right - left) / 2; + if (nums[mid] < nums[0]) { // [False,...,False,True,...True]で、Trueの左端が答えになる + right = mid - 1; // 基本True側にいるが、終了時にFalseに来る + } + else { + left = mid + 1; // 基本False側にいるが、終了時にTrueに来る + } + } +// 終了状態は以下のよう。leftの位置が答えに +// [False,...,False,True,...True] +// right "left" + return nums[left % numsSize]; // [False,...,False]タイプに対応([0,1,2,3]のケースに対応) +} + +int findMin(int* nums, int numsSize) { + int left = 0, right = numsSize - 1; // leftとrightが交差して終了するケース + while (left <= right) { // leftとrightが交差して終了するケース + int mid = left + (right - left) / 2; + if (nums[mid] <= nums[numsSize - 1]) { // [False,...,False,True,...True]で、Trueの左端が答えになる + right = mid - 1; // 基本True側にいるが、終了時にFalseに来る + } + else { + left = mid + 1; // 基本False側にいるが、終了時にTureに来る + } + } + return nums[left]; +} + +