-
[LeetCode] 29. Divide Two Integers문제/LeetCode 2022. 5. 30. 21:33
카테고리 : Bit Manipulation
난이도 : Medium
2022/5/30 (월) 문제.
Divide Two Integers - LeetCode
Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.
leetcode.com
아이디어
dividend
와divisor
가 주어지고, 곱하기 연산자(*
), 나누기 연산자(/
), 나머지 연산자(%
)를 사용하지 않고 두 정수를 나눠야 한다.두 정수를 나눈 몫을 구해야 한다. 이때 정수를 제외한 소수 부분은 제외한다.
이 문제를 딱 보고 든 생각은
곱셈, 나눗셈, 나머지 연산자를 사용하지 않으면서 몫을 구한다 => 비트 연산자를 사용해야 하는구나
였다.
핵심 아이디어는 이렇다. 우리가 나눗셈을 할 때 몫을 구하는 건
나눠지는 수
에서나누는 수
를 얼마나 뺄 수 있는지 그 횟수를 구하는 것과 같다.dividend
가 30,divisor
가 2라고 생각해보자. 2를 최대 15번 뺄 수 있다. 2를 16번을 빼면 -2가 되기 때문에 이는 몫을 틀리게 구한 것이 된다.dividend
가 30,divisor
가 4일 때도 마찬가지다. 4를 최대 7번 뺄 수 있는데, 4를 8번 빼면 -2가 되기 때문에 몫을 잘못 구한 것이다.따라서 나눠지는 수에서 나누는 수를 최대 얼마나 뺄 수 있는지 횟수를 비트연산자를 사용해서 구하면 된다.
dividend
가 30,divisor
가 2인 경우를 생각해보자.30 / 2
=> 2가 30보다 작거나 같기 때문에, 30에서 2를 뺄 수 있다는 것을 알 수 있다. 그렇다면 2를 증가시켰을 때도 30으로 나눌 수 있는지를 확인한다.2에 shift left 연산(
<<
)을 해서 4로 증가시켰다. 참고로 shift left 연산을 하면 비트를 왼쪽으로 한 칸씩 미니 2를 곱한 효과가 난다.30 / 4
=> 4도 마찬가지로 30보다 작거나 같기 때문에 30을 4로 뺄 수 있다는 것을 알 수 있다.그렇다면 뺄 수를 어디까지 증가시킬 수 있을까? 빼는 수가 30보다 커지는 순간 뺄 수 없기 때문에 우리는 뺄 수를 16까지만 증가할 수 있다는 것을 알 수 있다.
핵심은 30에서 뺄 수 있는 가장 큰 수를 찾는 것이다. 이 과정에서
divisor
는 총 몇 번 빠졌는지 같이 확인해보자.- 만약 빼는 수가 2라면
divisor
를 뺀 횟수는 1회가 된다. - 만약 빼는 수가 4라면
divisor
를 뺀 횟수는 2회가 된다. - 만약 빼는 수가 8이라면
divisor
를 뺀 횟수는 4회가 된다. - 만약 빼는 수가 16이라면
divisor
를 뺀 횟수는 8회가 된다.
이는 당연한 건데, 빼야 하는 수가 매번 2배가 되니 이에 따라 빼게 되는 횟수도 2배가 되는 것이다. 따라서 30에서 16을 빼게 되면 14가 남고, 지금까지
divisor
2를 총 8회 뺀 걸 알게 된다.이제 나머지
14
에 대해서도 똑같은 과정을 반복한다. 14에서 뺄 수 있는 가장 큰 수는 8, 뺀 횟수는 이전에 뺀 횟수 8회에 새로 뺀 횟수 4회를 더해 12번이 된다. 남은 수는 14 - 8 인 6이 된다.이런식으로 남은 수가
divisor
보다 크거나 같을때까지 계속 같은 과정을 반복한다. 만약 남은 수가divisor
보다 작으면divisor
로 뺄 수 없기 때문이다.코드
위에서 생각한 걸 코드로 옮겨봤다.
class Solution: def divide(self, dividend: int, divisor: int) -> int: # overflow에 대한 예외 처리를 해준다 if (dividend == -2147483648 and divisor == -1): return 2147483647 # dividend, divisor의 부호에 따라 정해지는 몫의 부호가 된다. multiplier = 1 # dividend, divisor를 모두 계산하기 편하게 양수로 바꿨다. if dividend < 0: dividend = -dividend multiplier = -multiplier if divisor < 0: divisor = -divisor multiplier = -multiplier # 남은 빼야 할 수 left = dividend # 몫 quotient = 0 # 남은 수가 divisor보다 크거나 같을 때만 계속 반복할 수 있다. while left >= divisor: # 내부 while loop에서 사용할 임시 몫(divisor를 빼는 횟수)이다. temporalQuotient = 1 # 빼게 될 수다. 우리의 목표는 이 currentNumber의 최댓값을 구하는 것이다. currentNumber = divisor # 빼야 할 최대 수를 구한다. while True: nextNumber = currentNumber << 1 # 뺄 수가 남은 수보다 작거나 같으면 뺄 수 있다 if nextNumber <= left: # 빼는 횟수, 뺄 수를 모두 두 배로 만든다. temporalQuotient = temporalQuotient << 1 currentNumber = nextNumber # 만약 빼야 할 수가 남은 수보다 더 커지게 되면 진행 할 수 없다. else: left -= currentNumber quotient += temporalQuotient break return quotient * multiplier
반응형'문제 > LeetCode' 카테고리의 다른 글
[LeetCode] 29. Divide Two Integers (0) 2022.06.16 - 만약 빼는 수가 2라면