문제 소개 양의 정수 n이 주어졌을 때, 다음 두 가지 연산을 수행할 수 있다고 가정해 보겠습니다. n이 짝수라면, n을 n/2로 대체합니다. n이 홀수라면, n을 n+1 또는 n-1 중 하나로 대체합니다. 우리가 구해야 할 것은 n을 1로 만들기 위해 필요한 최소 대체 횟수입니다. 예를 들어 n이 7이라면 정답은 4입니다. 7 → 8 → 4 → 2 → 1 또는 7 → 6 → 3 → 2 → 1의 경로를 거치면 딱 4번의 연산만으로 1에 도달할 수 있기 때문입니다. 문제 해결 접근법 이 문제는 그리디(Greedy) 기법으로 효율
중복된 값이 존재할 수 있는 정수 배열이 주어졌을 때, 특정 target 숫자에 해당하는 인덱스를 무작위로 하나 골라 반환하는 문제를 생각해 봅시다. 단, target은 반드시 배열 안에 존재한다고 가정합니다. 예를 들어 배열이 [1, 2, 3, 3, 3]이라면 pick(3)을 호출했을 때 인덱스 2, 3, 4 중 하나가 동등한 확률로 반환되어야 합니다. 접근 방법: 저수지 샘플링(Reservoir Sampling) 데이터의 크기를 미리 알지 못하거나 스트림 형태로 입력이 들어오는 상황에서도 균등한 확률로 샘플을 추출할 수 있는
문제 개요비어 있지 않은 숫자 배열 a₀, a₁, a₂, …, aₙ₋₁이 주어졌을 때(단, 0 ≤ aᵢ < 2³¹), 0 ≤ i, j < n 조건을 만족하는 aᵢ XOR aⱼ 값 중 최댓값을 구하는 것이 목표입니다.예를 들어 입력 배열이 [3, 10, 5, 25, 2, 8]이라면 출력은 28이 됩니다. 이는 5 XOR 25 = 28이 만들 수 있는 가장 큰 값이기 때문입니다.모든 쌍을 일일이 비교하는 방법은 O(n²)의 시간이 걸리지만, 이진 트라이(Binary Trie) 자료구조를 활용하면 O(n × 32) 시간 복잡도로 훨씬 효
문제 개요두 개의 비어 있지 않은 연결 리스트가 각각 음수가 아닌 정수를 나타낸다고 가정해 봅시다. 이때 가장 큰 자릿수(최상위 자릿수)가 맨 앞에 오며, 각 노드에는 한 자릿수만 저장되어 있습니다. 우리는 이 두 수를 더한 결과를 다시 연결 리스트 형태로 반환해야 합니다.예를 들어 [7, 2, 4, 3]과 [5, 6, 4]를 더하면 결과는 [7, 8, 0, 7]이 됩니다. 실제 숫자로 계산하면 7243 + 564 = 7807과 같습니다.왜 스택을 사용할까?자릿수가 역순(일의 자리부터)으로 저장되어 있다면 순서대로 더하면 되지만,
문제 개요단일 스레드(single-threaded) CPU에서 여러 함수를 실행한다고 가정해 보겠습니다. 각 함수는 0부터 N-1 사이의 고유한 ID를 가지며, 함수가 호출되거나 종료되는 시점을 나타내는 로그가 타임스탬프 순서대로 저장됩니다.각 로그는 다음과 같은 형식의 문자열입니다: {function_id}:{start | end}:{timestamp}. 예를 들어 0:start:3은 ID가 0인 함수가 타임스탬프 3의 시작 시점에 실행을 시작했다는 뜻이고, 1:end:2는 ID가 1인 함수가 타임스탬프 2의 마지막 시점에 종료되
문제 소개 어떤 상점에서 여러 종류의 상품을 판매하고 있다고 가정해 보겠습니다. 각 상품에는 고유한 가격이 매겨져 있고, 상점에서는 특별 제안(Special Offer)이라 불리는 할인 행사도 함께 진행하고 있습니다. 하나의 특별 제안은 서로 다른 종류의 상품을 한 개 이상 묶어 할인된 가격에 판매하는 형태입니다. 우리에게는 세 가지 정보가 주어집니다. 상품별 가격 목록(price), 특별 제안 목록(special), 그리고 각 상품을 정확히 몇 개씩 구매해야 하는지를 나타내는 목록(needs)입니다. 이때 특별 제안을 최적으로 활
Dota2 세계에는 라디언트(Radiant)와 다이어(Dire)라는 두 진영이 존재합니다. Dota2 상원은 두 진영 출신 의원들로 구성되어 있으며, 게임 변경 사항에 대한 결정을 내리기 위해 투표를 진행합니다. 문제 개요 투표는 라운드 기반 절차로 진행됩니다. 각 라운드마다 의원은 다음 두 가지 권리 중 하나를 행사할 수 있습니다. 권리 박탈 − 한 의원은 다른 의원의 권리를 박탈하여, 해당 의원이 이번 라운드와 이후 모든 라운드에서 투표권을 잃게 만들 수 있습니다. 승리 선언 − 만약 어떤 의원이 아직 투표권을 가진 의원들이
문제 개요 정수 배열 asteroids에는 일렬로 나열된 소행성들이 담겨 있습니다. 각 원소에서 절댓값은 소행성의 크기를, 부호는 이동 방향을 나타냅니다. 양수는 오른쪽으로, 음수는 왼쪽으로 이동하며, 모든 소행성은 동일한 속도로 움직입니다. 우리가 구해야 할 것은 모든 충돌이 끝난 후 소행성들의 최종 상태입니다. 충돌 규칙은 다음과 같습니다. 두 소행성이 만나면 크기가 작은 쪽이 폭발합니다. 크기가 같다면 두 소행성 모두 폭발합니다. 같은 방향으로 움직이는 소행성은 절대 만나지 않습니다. 예를 들어 입력이 [5, 10, -5]
문제 설명 정수로 이루어진 배열 nums가 주어졌다고 가정해 보겠습니다. 우리는 이 배열에 다음과 같은 연산을 수행할 수 있습니다. 각 연산에서는 nums[i]를 하나 골라 삭제하고, 그 대가로 nums[i]만큼의 점수를 얻습니다. 단, nums[i] - 1 또는 nums[i] + 1과 값이 같은 모든 원소도 함께 삭제해야 합니다. 초기 점수는 0이며, 이러한 연산을 통해 얻을 수 있는 최대 점수를 구하는 것이 목표입니다. 예를 들어 입력이 [3,4,2]라면 출력은 6이 됩니다. 먼저 4를 삭제하면 4점을 얻게 되고, 조건에 따라
문제 소개도미노(Domino)와 트로미노(Tromino), 두 가지 종류의 조각이 있다고 가정해 봅시다. 이 조각들은 아래 그림과 같이 자유롭게 회전하여 배치할 수 있습니다.문제 정의타일링(tiling)에서는 보드 위의 모든 칸이 반드시 타일로 덮여 있어야 합니다. 두 타일링 결과는 4방향(상하좌우)으로 인접한 두 칸 중에서, 정확히 한쪽 타일링에서만 그 두 칸이 동일한 타일로 덮여 있는 경우에만 서로 다른 것으로 간주합니다.N이 주어졌을 때, 2×N 크기의 보드를 타일링할 수 있는 서로 다른 방법의 수를 구하는 것이 목표입니다.예
문제 설명 소문자로만 이루어진 두 문자열 S와 T가 주어집니다. S에는 어떤 문자도 두 번 이상 나타나지 않으며, S는 미리 어떤 사용자 지정 순서에 따라 정렬되어 있습니다. 우리가 할 일은 T의 문자들을 재배열하여 S의 정렬 순서와 일치하도록 만드는 것입니다. 좀 더 구체적으로 말하면, S에서 x가 y보다 앞에 나온다면 결과 문자열에서도 x는 y보다 앞에 위치해야 합니다. 단, S에 등장하지 않는 문자들은 결과 문자열의 어느 위치에 와도 상관없습니다. 예를 들어 S = cba, T = abcd라고 가정해 보겠습니다. 이때 출력은
문제 개요양의 정수로 이루어진 배열 A와 두 개의 양의 정수 L, R이 주어집니다. 이때, 부분 배열 안의 최댓값이 L 이상 R 이하가 되는 (연속된, 비어 있지 않은) 부분 배열의 개수를 구하는 것이 목표입니다.예를 들어 A = [2,1,4,3], L = 2, R = 3이라고 해보겠습니다. 조건을 만족하는 부분 배열은 [2], [2,1], [3]으로 총 세 가지이므로 정답은 3이 됩니다.접근 방법이 문제는 각 인덱스를 끝점으로 하는 유효한 부분 배열의 개수를 누적하는 방식으로 선형 시간(O(n))에 해결할 수 있습니다. 핵심 변수
방향성을 가지면서 사이클이 없는 그래프, 즉 방향 비순환 그래프(DAG)에 N개의 노드가 있다고 가정해 봅시다. 우리의 목표는 노드 0에서 노드 N-1까지 이어지는 가능한 모든 경로를 찾아, 어떤 순서로든 반환하는 것입니다.그래프는 다음과 같은 형태로 주어집니다. 노드 번호는 0, 1, ..., graph.length - 1이며, graph[i]는 간선 (i, j)가 존재하는 모든 노드 j의 목록을 담고 있습니다.예를 들어 입력이 [[1,2], [3], [3], []]와 같다면, 출력은 [[0,1,3], [0,2,3]]이 됩니다.
길이가 같은 0이 아닌 두 개의 정수 수열 A와 B가 있다고 가정해 봅시다. 우리는 A[i]와 B[i]의 원소를 서로 교환(swap)할 수 있으며, 이때 두 원소는 각각의 수열에서 반드시 동일한 인덱스 위치에 있어야 합니다. 몇 번의 스왑을 거친 후, A와 B 두 수열 모두 엄격하게 증가(strictly increasing)하는 상태가 되어야 합니다. 목표는 이 조건을 만족하기 위한 최소 스왑 횟수를 구하는 것입니다.문제 예시예를 들어 입력이 A = [1, 3, 5, 4], B = [1, 2, 3, 7]이라면, 정답은 1입니다. A
카멜케이스 매칭(Camelcase Matching)은 문자열 처리 능력을 키울 수 있는 대표적인 알고리즘 문제입니다. 쿼리 문자열 목록과 하나의 패턴이 주어졌을 때, 각 쿼리가 패턴과 일치하는지 여부를 불리언(Boolean) 리스트로 반환해야 합니다. 즉, answer[i]는 queries[i]가 패턴과 일치하는 경우에만 true가 됩니다.여기서 말하는 일치의 조건은 다음과 같습니다. 패턴 단어에 임의의 소문자들을 삽입했을 때 해당 쿼리 단어와 완전히 같아질 수 있다면 두 단어는 일치하는 것으로 간주합니다. 대소문자의 순서는 그대로
문제 개요N × N 크기의 격자(grid)가 주어지며, 각 칸은 0(물) 또는 1(육지)의 값만 가집니다. 이때 가장 가까운 육지 칸까지의 거리가 최대가 되는 물 칸을 찾아 그 거리를 반환해야 합니다.거리는 맨해튼 거리(Manhattan distance)를 사용하며, 두 칸 (x0, y0)과 (x1, y1) 사이의 거리는 |x0 − x1| + |y0 − y1|로 계산합니다. 만약 격자에 육지만 있거나 물만 있다면 -1을 반환합니다.101000101예를 들어 위의 3×3 격자에서 출력값은 2입니다. 중앙에 있는 칸 (1, 1)이 네
문제 소개여러 건의 거래(transaction) 정보가 주어졌다고 가정해 보겠습니다. 어떤 거래가 아래 조건 중 하나라도 만족한다면, 그 거래는 잘못된(invalid) 거래일 가능성이 있습니다.거래 금액이 1,000달러($1,000)를 초과하는 경우같은 이름의 다른 거래가 다른 도시에서 발생했으며, 두 거래의 시간 차가 60분 이내(60분 포함)인 경우각 거래 문자열 transactions[i]는 쉼표(,)로 구분된 값들로 구성되며, 순서대로 거래자 이름, 시간(분 단위), 금액, 도시를 나타냅니다. 주어진 거래 목록에서 잠재적으로
문제 개요정수 배열 arr과 정수 k가 주어졌을 때, 원본 배열을 k번 반복하여 이어 붙인 새로운 배열을 만든다고 가정해 봅시다. 예를 들어 arr = [1, 2]이고 k = 3이라면, 결과 배열은 [1, 2, 1, 2, 1, 2]가 됩니다.목표는 이렇게 확장된 배열에서 최대 부분 배열 합(maximum sub-array sum)을 구하는 것입니다. 단, 부분 배열의 길이는 0이 될 수도 있으며, 이 경우 합은 0으로 처리합니다. 또한 정답이 매우 커질 수 있으므로 10^9 + 7로 나눈 나머지를 구해야 합니다.예를 들어 입력이 [
문제 설명Q, W, E, R 네 종류의 문자로만 이루어진 문자열이 있다고 가정해 봅시다. 문자열의 길이를 n이라 할 때, 각 문자가 정확히 n/4번씩 등장하면 이 문자열을 균형 잡힌(balanced) 문자열이라고 합니다. 우리가 구해야 하는 값은, 원본 문자열을 균형 잡힌 상태로 만들기 위해 동일한 길이의 다른 문자열로 교체할 수 있는 부분 문자열의 최소 길이입니다.예를 들어 s = QQWE라면 답은 1입니다. Q 하나를 R로 바꾸면 RQWE가 되어 균형이 맞기 때문입니다. 이미 균형이 잡혀 있는 문자열이라면 0을 반환합니다.접근
두 개의 정수 n과 start가 주어졌을 때, 다음 조건을 만족하는 순열 p(0, 1, 2, ..., 2^n − 1)를 반환하는 것이 목표입니다.p[0] = start 여야 합니다.인접한 두 원소 p[i]와 p[i+1]은 이진 표현에서 단 한 비트만 달라야 합니다.첫 번째 원소 p[0]와 마지막 원소 p[2^n − 1] 역시 이진 표현에서 단 한 비트만 달라야 합니다. 즉, 수열이 순환(circular) 구조를 가져야 합니다.예시예를 들어 n = 2이고 start = 3이라면, 반환되는 배열은 [3, 2, 0, 1]입니다. 이를 이