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]; +} + + 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..b9dfba8 --- /dev/null +++ b/leetcode60/153. Find Minimum in Rotated Sorted Array/memo.md @@ -0,0 +1,55 @@ + +# 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回ずつ行った。 +エッジケースをそれぞれ手元で書きながら確認しないと厳しい。 +何もせずに書けはするが、脳死で書くだけなので内容を把握したことにはならなそう。 +トータル3時間かかった。 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..71f67be --- /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, target = nums[0]; + while (left < right) { + int mid = left + (right - left) / 2; + if (nums[mid] < target) { + right = mid; + target = nums[mid]; + } + else { + left = mid + 1; + } + } + return target; +}