서로 다른 액면가의 동전들과 하나의 목표 금액(amount)이 주어졌을 때, 그 금액을 정확히 만들기 위해 필요한 최소 동전 개수를 계산하는 함수를 작성해야 합니다. 만약 어떤 동전 조합으로도 해당 금액을 만들 수 없다면 -1을 반환합니다.예를 들어 동전 배열이 [1, 2, 5]이고 목표 금액이 64라면, 출력은 14가 됩니다. 이는 12×5 + 2 + 2 = 64, 즉 5원짜리 12개와 2원짜리 2개로 금액을 구성할 수 있기 때문입니다.문제 해결 접근 방식이 문제는 대표적인 동적 계획법(Dynamic Programming) 유형으
문제 설명음수가 아닌 숫자로 이루어진 리스트 nums와 음수가 아닌 값 k가 주어집니다. 우리는 nums에서 하나의 양수를 선택하여 1만큼 감소시키는 연산을 수행할 수 있습니다. 이때 리스트에서 모든 인접한 두 값의 합이 k 이하가 되도록 만들기 위해 필요한 최소 연산 횟수를 구해야 합니다.만약 답이 매우 큰 값이라면 결과를 10^9 + 7로 나눈 나머지를 반환합니다.예를 들어, 입력이 nums = [4, 6, 2, 5], k = 6이라면 출력은 5가 됩니다. 리스트를 [3, 3, 1, 4]로 감소시키면 총 5번의 감소 연산이 수행
문제 개요숫자로 이루어진 리스트 nums와 두 값 size, k가 주어진다고 가정해 봅시다. 사용할 수 있는 연산은 다음과 같습니다.길이가 정확히 size인 연속된 부분 리스트를 하나 선택한다.선택한 부분 리스트의 모든 요소를 1씩 증가시킨다.이 연산을 최대 k번 수행할 수 있을 때, 리스트 전체에서 얻을 수 있는 최솟값의 최댓값을 구하는 것이 목표입니다.예시입력이 nums = [2, 5, 2, 2, 7], size = 3, k = 2라고 해보겠습니다.첫 번째 연산으로 인덱스 0~2의 [2, 5, 2]를 증가시키면 [3, 6, 3,
문제 이해하기길이가 같은 두 개의 숫자 리스트 A와 B가 주어져 있다고 가정해 보겠습니다. 또한 각 원소가 [i, j] 형태인 2차원 리스트 C가 주어지는데, 이는 A[i]와 A[j]를 원하는 만큼 자유롭게 교환(swap)할 수 있음을 의미합니다. 우리가 구해야 하는 것은 교환 작업을 마친 후 A[i] = B[i]를 만족하는 쌍의 최대 개수입니다.예를 들어 입력이 다음과 같다면,A = [5, 6, 7, 8], B = [6, 5, 8, 7], C = [[0, 1], [2, 3]]정답은 4가 됩니다. A[0]과 A[1]을 교환하고, A
문제 개요이진 트리가 하나 주어졌다고 가정해 봅시다. 이때 부모와 자식 관계에 있는 두 노드는 동시에 선택할 수 없다는 조건 하에서, 선택한 노드 값들의 최대 합을 구하는 것이 목표입니다.예를 들어 입력이 다음과 같다면,출력은 17이 됩니다. 10, 4, 3은 서로 부모-자식 관계(인접)가 아니기 때문에 세 노드를 모두 함께 선택할 수 있기 때문입니다.풀이 접근 방법이 문제는 트리 위에서의 동적 계획법(DP)으로 효율적으로 해결할 수 있습니다. 핵심 아이디어는 각 노드마다 두 가지 상태를 계산하는 것입니다.현재 노드를 포함했을 때의
문제 개요소문자 알파벳으로만 이루어진 문자열 리스트 words가 주어졌을 때, 서로 공통된 문자를 하나도 가지지 않는 두 단어를 골라 그 길이의 합이 최대가 되도록 만드는 프로그램을 작성해 보겠습니다.예를 들어 입력이 [abcd, mno, abdcmno, amno]라고 한다면, 공통 문자가 전혀 없는 단어 쌍은 abcd와 mno입니다. 이때 길이의 합은 4 + 3 = 7이므로 출력값은 7이 됩니다.접근 방식: 비트마스크(Bitmask) 활용두 단어에 공통 문자가 있는지 확인하는 가장 직관적인 방법은 모든 문자를 일일이 비교하는 것이
Python으로 정렬된 K개의 리스트 병합하기여러 개의 정렬된 리스트가 주어졌을 때, 이를 하나의 정렬된 리스트로 병합해야 하는 상황은 실무와 코딩 테스트에서 매우 자주 등장합니다. 이 문제는 힙(heap) 자료구조를 활용하면 효율적으로 해결할 수 있습니다.예를 들어 [1, 4, 5], [1, 3, 4], [2, 6] 세 개의 정렬된 리스트가 있다면, 병합 결과는 다음과 같습니다.[1, 1, 2, 3, 4, 4, 5, 6]알고리즘 접근 방식핵심 아이디어는 각 리스트의 첫 번째 원소만 힙에 넣어두고, 가장 작은 값을 꺼낼 때마다 해당
0과 1로만 이루어진 리스트가 있다고 가정해 보겠습니다. 우리는 리스트의 앞쪽 또는 뒤쪽에서만 값을 삭제할 수 있으며, 삭제가 끝난 뒤 남은 리스트에 포함된 0과 1의 개수가 서로 같아지도록 만들어야 합니다. 이 문제의 목표는 이때 필요한 최소 삭제 횟수를 구하는 것입니다. 예를 들어 입력이 nums = [1, 1, 1, 0, 0, 1]이라면 정답은 2입니다. 맨 앞의 1 하나와 맨 뒤의 1 하나를 각각 삭제하면 [1, 1, 0, 0]이 되어 1 두 개와 0 두 개로 균형이 맞기 때문입니다. 문제 해결 아이디어 핵심은 균형이 맞는
두 개의 리스트 L1과 L2가 주어졌을 때, L1의 어떤 숫자와 L2의 어떤 숫자 사이의 차이 중 가장 작은 값을 찾아야 한다고 가정해 봅시다.예를 들어 입력이 L1 = [2, 7, 4], L2 = [16, 10, 11]이라면, 출력은 3이 됩니다. 가장 작은 차이가 10 - 7 = 3이기 때문입니다.문제 해결 접근 방법이 문제는 투 포인터(Two Pointer) 기법을 활용하면 효율적으로 해결할 수 있습니다. 두 리스트를 모두 정렬한 후, 각 리스트를 가리키는 포인터를 하나씩 두고 비교해 나가는 방식입니다. 단계별로 살펴보면 다음
숫자로 이루어진 리스트 nums가 있다고 가정해 보겠습니다. 우리는 리스트의 한 요소를 임의의 값으로 바꿀 수 있는 연산을 사용할 수 있으며, 이 연산은 최대 3번까지만 수행할 수 있습니다. 이때 연산을 마친 뒤 리스트에서 최댓값과 최솟값의 차이가 가능한 한 작아지도록 만드는 것이 목표입니다. 예를 들어 입력이 nums = [2, 3, 4, 5, 6, 7]이라면 출력은 2입니다. 리스트를 [4, 3, 4, 5, 4, 4]로 바꾸면 최댓값 5에서 최솟값 3을 뺀 5 − 3 = 2가 되기 때문입니다. 문제 해결 접근 방법 이 문제는 다
문제 설명각 행에 3개의 값이 담긴 작업(task) 행렬이 하나 있고, 또 다른 값 k가 주어진다고 가정해 봅시다. 우리는 tasks에서 k개의 행을 선택해 이를 S라고 부르며, 다음 합이 최소가 되도록 선택한 뒤 그 결과를 반환해야 합니다.max(S[0, 0], S[1, 0], ..., S[k-1, 0]) + max(S[0, 1], S[1, 1], ..., S[k-1, 1]) + max(S[0, 2], S[1, 2], ..., S[k-1, 2])쉽게 말해, 3개의 열 각각이 비용에 기여하며 그 값은 S 안에서 해당 열의 최댓값으로
숫자로 이루어진 리스트 nums와 정수 k가 주어졌을 때, min(S) + max(S) ≤ k 조건을 만족하는 공집합이 아닌 부분 집합 S의 개수를 구하는 문제입니다. 여기서 주의할 점은 부분 집합이 멀티셋(multiset)처럼 취급된다는 것입니다. 부분 집합은 값이 아니라 리스트의 특정 요소(인덱스)를 기준으로 선택되기 때문에, 값이 같더라도 서로 다른 요소라면 별개의 부분 집합으로 계산됩니다. 예시 입력이 nums = [2, 2, 5, 6], k = 7이라면 정답은 6이며, 만들 수 있는 부분 집합은 다음과 같습니다. [2]
이진 트리가 주어졌을 때, 가장 자주 나타나는 하위 트리 합계(most frequent subtree sum)를 찾아야 합니다. 여기서 노드의 하위 트리 합계란 해당 노드 자신을 포함하여 그 아래에 있는 모든 노드 값의 합을 의미합니다.예를 들어 입력이 다음과 같다고 가정해 보겠습니다.이 경우 출력은 3이 됩니다. 3이라는 합계가 총 두 번 나타나기 때문인데, 한 번은 왼쪽 리프 노드의 값으로, 또 한 번은 3 - 6 + 6의 계산 결과로 등장합니다.해결 접근 방법이 문제는 후위 순회(post-order traversal) 방식의
n명의 사람을 0부터 n-1까지의 숫자로 표현하고, 친구 관계를 담은 리스트 friends가 주어졌다고 가정해 봅시다. 여기서 friends[i][0]과 friends[i][1]은 서로 친구인 두 사람을 의미합니다. 우리가 확인해야 할 것은 모든 사람이 최소 한 명 이상의 친구를 가지고 있는지 여부입니다.예를 들어 n = 3이고 friends = [[0, 1], [1, 2]]라고 입력하면 출력은 True가 됩니다. 0번 사람은 1번 사람의 친구이고, 1번 사람은 0번과 2번 양쪽 모두의 친구이며, 2번 사람은 1번 사람의 친구이기
모든 요소가 양수인 배열 nums가 있다고 가정해 봅시다. 우리는 현재 인덱스 0에 있으며, 배열의 각 요소는 해당 위치에서 이동할 수 있는 최대 점프 거리를 의미합니다. 목표는 가장 적은 점프 횟수로 마지막 인덱스(n-1, n은 배열의 크기)에 도달하는 것입니다.예를 들어 배열이 [2,3,1,1,4]라면 출력은 2가 됩니다. 인덱스 0에서 인덱스 1로 점프한 뒤, 다시 인덱스 4(마지막 인덱스)로 점프하면 총 두 번의 점프로 목표에 도달할 수 있기 때문입니다.문제 해결 접근 방식이 문제는 그리디(Greedy) 알고리즘을 사용하면
0과 1로 이루어진 이진 행렬(binary matrix)이 있다고 가정해 보겠습니다. 우리가 해야 할 일은 이 행렬 안에 섬이 몇 개 있는지 세는 것입니다. 여기서 1은 육지를, 0은 물을 의미합니다. 즉, 섬이란 서로 인접한 1들의 그룹으로, 그 둘레가 모두 물(0)로 둘러싸여 있는 영역을 말합니다.단, 이 문제에서 인접(adjacent)은 수평 또는 수직 방향만 고려하며, 대각선 방향은 인접으로 취급하지 않습니다.예를 들어 입력 행렬이 다음과 같다면,101000010001100000001101111101출력 결과는 4가 됩니다.
문자열 s가 주어졌을 때, 해당 문자열 안에 존재하는 회문(palindrome) 부분 문자열의 개수를 구하는 것이 목표입니다.예를 들어 입력 문자열이 s = level이라면 출력은 7이 됩니다. 회문 부분 문자열이 [l, e, v, e, l, eve, level]로 총 7개이기 때문입니다.문제 해결 접근 방식이 문제는 각 인덱스를 중심으로 삼아 양쪽으로 확장해 가며 회문 여부를 확인하는 방식으로 효율적으로 해결할 수 있습니다.구체적인 알고리즘은 다음과 같습니다.check_palindrome() 함수를 정의합니다. 이 함수는 문자열과
문자열 s가 주어졌을 때, 이 문자열의 모든 회문(palindrome) 부분 문자열의 길이가 홀수인지 확인하는 문제입니다.예를 들어 입력이 s = level이라면, 출력은 True가 됩니다. level의 회문 부분 문자열인 l, e, v, eve, level은 모두 길이가 홀수이기 때문입니다.접근 방법이 문제의 핵심 아이디어는 매우 간단합니다. 문자열에 같은 문자가 연속해서 나타난다면, 그 두 문자 자체가 길이 2짜리 회문 부분 문자열(짝수 길이)이 됩니다.따라서 해결 절차는 다음과 같습니다.인덱스 1부터 문자열 길이까지 반복합니다
숫자로 이루어진 리스트 nums가 주어졌을 때, 새로운 리스트를 만들어야 합니다. 새 리스트의 각 인덱스 i에 해당하는 값은 원본 리스트에서 인덱스 i의 요소 하나를 제외한 나머지 모든 숫자의 곱입니다. 단, 이 문제는 나눗셈을 사용하지 않고 풀어야 한다는 조건이 있습니다.예를 들어 입력이 nums = [2, 3, 4, 5, 6]이라면 출력은 [360, 240, 180, 144, 120]이 됩니다. 각 위치의 값은 해당 요소를 제외한 나머지 숫자들을 모두 곱한 결과입니다.문제 해결 접근 방법나눗셈 없이 이 문제를 해결하려면 왼쪽 누
두 개의 문자열 S와 T가 주어졌을 때, 이 두 문자열이 편집 거리(edit distance) 0 또는 1 이내인지 확인하는 문제를 살펴보겠습니다.여기서 말하는 편집 연산은 다음 세 가지 중 하나를 의미합니다.문자 하나 삭제하기문자 하나 추가하기기존 문자를 다른 문자로 교체하기예시로 이해하기예를 들어 입력이 S = hello, T = hallo라고 가정해 보겠습니다. e를 a로 한 번만 교체하면 되므로 편집 거리는 1이고, 따라서 출력은 True가 됩니다.반면 두 문자열의 길이 차이가 2 이상이라면, 어떤 편집 연산을 아무리 사용해