바위타는 두루미

8.5 재귀 곱셈 본문

Study/Interview준비

8.5 재귀 곱셈

DoRoMii 2019. 8. 4. 19:43
728x90

문제 

* 연산자를 사용하지 않고 양의 정수 두 개를 곱하는 재귀함수를 작성하라.

덧셈, 뺄셈, 비트 쉬프팅 연산을 사용할 수 있지만 사용횟수를 최소화해야한다. 

 

접근법

곱셈은 격자판 안의 셀의 갯수와 같다고 볼 수 있다. 

7*8은 7*8 격자판의 셀의 갯수를 세는 것과 같을 테니까 말이다.

그렇다면 셀의 갯수는 어떻게 샐 수 있을 까?

절반을 세고 이것을 곱절로 만들어 가는 과정을 재귀적으로 처리할 수 있을 것이다. 

def Solution(a, b):
    small = a if a<b else b
    big = a if a<b else b
    return minProduct(small,big)

def minProduct(small,big):
    
    if small == 0 :
        return 0
    if small == 1:
        return big

    s = small >>1
    side1 = minProduct(s, b)
    side2 = side1 if small%2==0 else minProduct(small-s, b)
    return side1 +side2

이 코드에도 minProduct가 반복적으로 호출됨을 알 수 있다.

b는 유지되고 s에 따라 달라지므로 s에 대해 cache를 설정하여 좀더 효율적으로 개선할 수있다.

def Solution(a, b):
    memo = {}
    small = a if a<b else b
    big = a if a<b else b
    return minProduct(small,big,memo)

def minProduct(small,big,memo):

    if small == 0 :
        return 0
    if small == 1:
        return big
    if small in memo:
        return memo[small]

    s = small >>1
    side1 = minProduct(s, b)
    side2 = side1 if small%2==0 else minProduct(small-s, b)
    memo[small] = side1 + side2
    return side1 +side2

 

-더 나은 해결법

현재는 짝수인 경우에는 곱절로 더하지만, 홀수인 경우에는 작은 수의 나머지 반에 대해서도 탐색을 하고 있다.

하지만 minProduct(31,35)를 보면 minProduct(15, 35), minProduct(16,35)를 호출한다. 하지만 이것은 불필요하다

31 = 15*2 + 1 이기 떄문에 31 * 35 = 2*15*35 +35 가 되고 

그말은 즉 minProduct(15,35) *2 + 35  만 해주면 된다는 것이다. 

이런식으로 처리를 한다면 

짝수인 경우에는 곱절한 값을 리턴할 것이고, 홀수인경우에는 곱절한값 + big 값을 반환할 것이다.

그러면 매 단계 재귀 호출을 하넌만하고 호출을 할때 숫자도 매우 점점 작아지고 같은 호출을 부르는 일도 없어서 효율이 좋아진다.

def Solution(a,b):
    small = a if a<b else b
    big = a if a<b else b
    return minProduct(small,big)

def minProduct(small,big):
    if small == 0:
        return 0
    if small == 1:
        return big

    s = small>>1
    side1 = minProduct(s,big)
    if small%2 ==0:
        return side1 + side1
    else :
        return side1 + side1 + big

 

'Study > Interview준비' 카테고리의 다른 글

8.7 중복없는 순열  (0) 2019.08.04
8.6 하노이타워  (0) 2019.08.04
8.4 부분집합  (0) 2019.08.04
8.3 마술인덱스  (0) 2019.08.04
8.1 트리플 스텝  (0) 2019.08.04
Comments