Description

Given a non-negative integer x, return the square root of x rounded down to the nearest integer. The returned integer should be non-negative as well.

You must not use any built-in exponent function or operator.

For example, do not use pow(x, 0.5) in c++ or x ** 0.5 in python.

Example 1:

  • Input: x = 4
  • Output: 2
  • Explanation: The square root of 4 is 2, so we return 2.

Example 2:

  • Input: x = 8
  • Output: 2
  • Explanation: The square root of 8 is 2.82842…, and since we round it down to the nearest integer, 2 is returned.

Constraints:

  • 0 <= x <= 231 - 1

💡 Hint 1:
Try exploring all integers. (Credits: @annujoshi)

💡 Hint 2:
Use the sorted property of integers to reduced the search space. (Credits: @annujoshi)

Submitted Code

class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        left_p = 0        # 왼쪽 포인터 시작 숫자 = 0
        right_p = x       # 오른쪽 포인터 시작 숫자 = x

        while left_p <= right_p:              
            mid = (left_p + right_p) // 2     # 왼쪽과 오른쪽의 가운데 숫자

            if mid * mid == x:
                return mid
            elif mid * mid > x:
                right_p = mid - 1
            else:
                left_p = mid + 1

        return right_p

Runtime: 9 ms | Beats 21.82%
Memory: 12.48 MB | Beats 28.58%

이진 탐색 알고리즘을 사용해서 풀어 보았다.

class Solution(object):
    def mySqrt(self, x):
        n = 0
        while n * n <= x:
            n += 1
        return n - 1

Brute Force 알고리즘으로, 매우 간단하지만 효율이 아주 낮았다.

Other Solutions

1st

class Solution:
    def mySqrt(self, x: int) -> int:
        if x == 0:
            return 0
        left, right = 1, x
        while left <= right:
            mid = (left + right) // 2
            if mid * mid == x:
                return mid
            elif mid * mid < x:
                left = mid + 1
            else:
                right = mid - 1
        return right

time complexity: 𝑂(log𝑥)
space complexity: 𝑂(1)

내가 제출한 코드와 거의 같지만 차이점은 x가 0인 경우를 먼저 거르고 왼쪽 포인트를 1부터 시작하는 것이다.

같은 원리지만 이 코드의 런타임이 거의 절반 정도 더 빨랐다.

2nd

class Solution:
    def mySqrt(self, x: int) -> int:
        return int(sqrt(x))

파이썬의 math 모듈에서 제공하는 math.sqrt() 함수를 사용할 경우 간단하게 작성 가능하고 0ms 내에 해결 가능했다.
리트 코드에 math 모듈이 자동 내장되어 있다는 것을 처음 알았다.

3rd

class Solution:
    def mySqrt(self, x: int) -> int:
        ans = x                         # x에서 시작
        while ans*ans > x:              # ans*ans가 x보다 작거나 같아지기 전까지 갱신식 반복
            ans = (ans + x//ans)//2
        return ans 

Newton-Raphson(뉴턴-랩슨) 방법을 사용한 예시로, 갱신식을 반복적으로 적용할수록 루트 x에 더 가까워지는 알고리즘이다. 요구하는 반환값이 int이기 때문에 갱신식의 / 연산자가 // 연산자로 대체됐다.

💡 Update Equation = answer = { answer + (x ÷ answer) } ÷ 2

ans = x = 8

8 = {8 + (8 // 8)} // 2 = (8 + 1) // 2 = 9 // 2 = 4   ← 4 * 4 = 16 
4 = {4 + (8 // 4)} // 2 = (4 + 2) // 2 = 6 // 2 = 3   ← 3 * 3 = 9
3 = {3 + (8 // 3)} // 2 = (3 + 2) // 2 = 5 // 2 = 2   ← 2 * 2 = 4
                                                        (loop over)

ans= 2

Leave a comment