Algorithm/Leetcode

[Leetcode] 153. Find Minimum in Rotated Sorted Array (python)

sahayana 2023. 9. 4. 23:13

#1.  문제

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/

 

Find Minimum in Rotated Sorted Array - LeetCode

Can you solve this real interview question? Find Minimum in Rotated Sorted Array - Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become: * [4,5,6,7,0,1,2] if it

leetcode.com

 

 

정렬된 정수 배열 nums가 1 부터 n번까지 순회한 상태 (옆으로 한칸씩 이동)라고 가정할 때, 최솟값을 찾는 문제

풀이는 O(logN)으로 풀이해야 한다.

Input: 
nums = [4,5,6,7,0,1,2]

Output: 
0

Explanation:
[0, 1, 2, 4, 5, 6]의 초기 배열이 4번 이동하여 [4,5,6,7,0,1,2]으로 변화

 

 


#2.  풀이

 

다른 풀이 방법을 고려하지 않고, 처음 생각에 매몰되어 결국 케이스 통과가 실패한 풀이

class Solution:
    def findMin(self, nums: List[int]) -> int:
        def search(left: int, right: int):

            mid = (left + right) // 2

            if left == right:
                return nums[0]

            if nums[mid] > nums[mid + 1]:
                return nums[mid + 1]
            elif nums[mid] < nums[mid + 1]:
                return search(mid + 1, right)
            else:
                return search(left, mid - 1)

        left, right = 0, len(nums) - 1

        return search(left, right)

 

별로 어렵지 않다고 생각했던 문제여서, 더 나은 방법을 고민하기 힘들었다.

이진탐색과 재귀를 이용해서 풀었는데, 아직도 충분히 최적화가 가능하다고 생각한다.

재귀를 이용한 더 쉬운 풀이가 있지만 문제 요구사항인 O(logN) 풀이에 위배된다.

 

솔루션을 참고한 풀이

class Solution:
    def findMin(self, nums: List[int]) -> int:

        left, right = 0, len(nums) - 1
        min_num = nums[0]

        while left <= right:

            if nums[left] < nums[right]:
                min_num = min(min_num, nums[left])
                break

            mid = (left + right) // 2
            min_num = min(min_num, nums[mid])

            if nums[mid] >= nums[left]:
                left = mid + 1
            else:
                right = mid - 1

        return min_num

문제의 핵심과 패턴을 다르게 생각하고 있던 것이 패착이었다.

오름차순 정렬과 오른쪽으로 한칸씩 이동한다는 것을 잘 생각해보면 쉽게 풀 수도 있었을 것 같은 아쉬운 문제.

 nums[mid] >= nums[left] 인 경우 오른쪽 배열에서 최솟값을 찾고, 반대의 경우 왼쪽 배열에 최솟값이 있으므로 왼쪽을 찾는다.
nums[left]와 비교를 하는 이유는 배열은 정렬된 상태이므로 nums[left]는 mid 기준 무조건 왼쪽 배열의 최솟값이기 때문이다.
ex) nums = [3, 4, 5, 1, 2], nums[mid] = 5 >= nums[left] = 3 이고, 즉 nums[left:mid+1] = [3,4,5] 이기 때문에 왼쪽은 찾을 필요가 없다.
이 과정에서 min값을 계속 갱신한다.