알고리즘

더하거나 빼거나

na_o 2021. 8. 26. 02:44
728x90

[문제]

음이 아닌 정수들로 이루어진 배열이 있다. 이 수를 적절히 더하거나 빼서 특정한 숫자를 만들려고 한다.

예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들기 위해서는 다음 다섯 방법을 쓸 수 있다.

-1+1+1+1+1 = 3

+1-1+1+1+1 = 3

+1+1-1+1+1 = 3

+1+1+1-1+1 = 3

+1+1+1+1-1 = 3

사용할 수 있는 숫자가 담긴 배열 numbers, 타겟 넘버 target_number이 매개변수로 주어질 때

숫자를 적절히 더하고 빼서 타겟 넘버를 만드는 방법의 수를 반환하시오

numbers = [1, 1, 1, 1, 1]
target_number = 3

 

 

 

[먼저 모든 경우의 수 구하는 함수 만들기]

No. 연산 결과값 타겟여부 연산자
1 +2 +3 +1 6   + + +
2 +2 +3 -1 4   + + -
3 +2 -3 +1 0 타겟! + - +
4 +2 -3 -1 -2   + - -
5 -2 +3 +1 2   - + +
6 -2 +3 -1 0 타겟! - + -
7 -2 -3 +1 -4   - - +
8 -2 -3 -1 -6   - - -

반복되는 구조를 축소할 수 있는 방법은
앞의 두 개의 연산자는 고정시키고
뒤의 연산자를 + 또는 -으로 바꾸면
2가지의 경우의 수가 추가적으로 생긴다

마지막의 원소를 뺄지/더할지에 따라 2가지 방법이 추가된다

결론) N의 길이의 배열에서 더하거나 뺀 모든 경우의 수는
        N -1 의 길이의 배열에서 마지막 원소를 더하거나 뺀 경우의 수를 추가하면 된다

# 먼저 좀 더 쉬운 숫자로 생각
numbers = [2, 3, 1]
target_number = 0

result = []  # 모든 경우의 수를 담기 위한 변수

# 모든 경우의 수 구하는 함수
# Arguments
# array: 음이 아닌 정수들로 이루어진 배열
# current_index: array의 현재 위치(인덱스)
# current_sum: 현재의 합
# all_ways: 모든 경우의수(관리하기 위한 배열)/ result 배열을 전달할것임
def get_all_ways_to_by_doing_plus_or_minus(array, current_index, current_cal, all_ways):
    if current_index == len(array):
        all_ways.append(current_cal)
        return
    get_all_ways_to_by_doing_plus_or_minus(array, current_index + 1, current_cal + array[current_index], all_ways)
    get_all_ways_to_by_doing_plus_or_minus(array, current_index + 1, current_cal - array[current_index], all_ways)

def get_count_of_ways_to_target_by_doing_plus_or_minus(array, target):
    # 구현해보세요!
    return 5


print(get_all_ways_to_by_doing_plus_or_minus(numbers, 0, 0, result))  # None
print(result)  # [6, 4, 0, -2, 2, 0, -4, -6]

 


풀이)

계산한 값이 타겟 값이랑 같아야 result_count를 1 올려야함

 

0 , 문자열, character 같은 변하지 않는 primitive type의 경우는
파이썬 내부에서 파라미터로 넘기면 그 값을 복제해서 새로운 값을  생성함!!!

numbers = [1, 1, 1, 1, 1]
target_number = 3

result_count = 0


# Arguments
# array: 음이 아닌 정수들로 이루어진 배열
# target: 만드려고 하는 수
# current_index: array의 현재 위치(인덱스)
# current_cal: 현재의 합
def get_count_of_ways_to_target_by_doing_plus_or_minus(array, target, current_index, current_cal):
    if current_index == len(array):
        if current_cal == target:
            global result_count     # global: 내부에서 외부 변수를 쓰겠다
            result_count += 1
        return
    get_count_of_ways_to_target_by_doing_plus_or_minus(array, target, current_index + 1,
                                                       current_cal + array[current_index])
    get_count_of_ways_to_target_by_doing_plus_or_minus(array, target, current_index + 1,
                                                       current_cal - array[current_index])


get_count_of_ways_to_target_by_doing_plus_or_minus(numbers, target_number, 0, 0)
print(result_count)  # 5

 

 

문제가 축소되는 과정에서는 재귀함수로 해결할 수 있다
헷갈리는 게 있다면 모든 경우의 수를 다 써보고 시도해보자

'알고리즘' 카테고리의 다른 글

정렬 - 선택정렬  (0) 2021.08.27
정렬 - 버블정렬  (0) 2021.08.26
배달의 민족 배달 가능 여부  (0) 2021.08.26
링크드 리스트 끝에서 K 번째 값 출력하기  (0) 2021.08.26
재귀함수 - 2  (0) 2021.08.24