|
| 1 | +class `Search-in-Rotated-Sorted-Array` { |
| 2 | + fun search(nums: IntArray, target: Int): Int { |
| 3 | + // log n -> 이진 탐색 |
| 4 | + // 이진 탐색 -> 왼쪽은 작고, 오른쪽은 크다 |
| 5 | + // 그렇다면.. 회전된 인덱스 기준으로 잘라서 좌우에서 각각 이진 탐색하면 가능하다 |
| 6 | + // 회전된 인덱스 어떻게 찾나? -> 이진 탐색해서 좌측이 더 크거나, 우측이 더 작으면 우측이 인덱스다 |
| 7 | + |
| 8 | + // 1단계: 이진 탐색해서 회전한 인덱스 찾기 |
| 9 | + // 2단계: 회전한 인덱스 기준으로 좌우 자르고, 각각 이진 탐색하기 |
| 10 | + // 3단계: 둘다 없으면 -1, 좌측 또는 우측에서 답 찾아서 반환 |
| 11 | + // 시간복잡도: O(log n), 공간복잡도: O(1) |
| 12 | + |
| 13 | + val rotatedIndex = findRotatedIndex(nums) |
| 14 | + val index = binarySearch(nums, 0, rotatedIndex - 1, target) |
| 15 | + // 왼쪽에 답이 있는지 |
| 16 | + if (index > -1) { |
| 17 | + return index |
| 18 | + } |
| 19 | + // 없으면 오른쪽 답 탐색해서 반환 |
| 20 | + return binarySearch(nums, rotatedIndex, nums.size - 1, target) |
| 21 | + } |
| 22 | + |
| 23 | + fun findRotatedIndex(nums: IntArray): Int { |
| 24 | + // nums[0] 이 nums[mid]보다 크면 rotated index 는 왼쪽에 있음 |
| 25 | + // 정렬되어있다면 위 조건이 될 수 없기 때문 |
| 26 | + var left = 0 |
| 27 | + var right = nums.size - 1 |
| 28 | + while (left <= right) { |
| 29 | + val mid = left + (right - left) / 2 |
| 30 | + // 좌측 값이 더 크면 rotated index |
| 31 | + if (0 < mid && nums[mid - 1] > nums[mid]) { |
| 32 | + return mid |
| 33 | + } |
| 34 | + // 왼쪽이 정렬되었는지 |
| 35 | + if (nums[0] <= nums[mid]) { |
| 36 | + left = mid + 1 |
| 37 | + } |
| 38 | + // 오른쪽이 정렬되었는지 |
| 39 | + else { |
| 40 | + right = mid - 1 |
| 41 | + } |
| 42 | + } |
| 43 | + return 0 |
| 44 | + } |
| 45 | + |
| 46 | + fun binarySearch(nums: IntArray, left: Int, right: Int, target: Int): Int { |
| 47 | + var left = left |
| 48 | + var right = right |
| 49 | + |
| 50 | + while (left <= right) { |
| 51 | + val mid = left + (right - left) / 2 |
| 52 | + if (nums[mid] == target) { |
| 53 | + return mid |
| 54 | + } |
| 55 | + if (nums[mid] < target) { |
| 56 | + left = mid + 1 |
| 57 | + } |
| 58 | + else { |
| 59 | + right = mid - 1 |
| 60 | + } |
| 61 | + } |
| 62 | + return -1 |
| 63 | + } |
| 64 | +} |
0 commit comments