자바스크립트 코딩테스트 강좌, 친구 관계 파악하기

코딩테스트에서는 종종 데이터 구조와 알고리즘 관련 문제가 출제됩니다. 특히 친구 관계를 파악하는 문제는 그래프 이론과 관련이 있으며, 많은 기업들이 이러한 문제를 통해 지원자의 논리적 사고와 코딩 능력을 평가합니다.

문제 설명

친구 관계를 파악하는 알고리즘 문제는 다음과 같습니다.
문제: 친구 관계 탐색
주어진 인원 N과 친구 관계를 나타내는 M개의 쌍이 있을 때, 특정 인원이 친구가 아닌 모든 사람들의 수를 구하는 함수를 작성하시오.

입력 형식

  • 첫 번째 줄: 사람의 수 N (1 ≤ N ≤ 100)
  • 두 번째 줄: 친구 관계의 수 M (1 ≤ M ≤ 1000)
  • 세 번째 줄: M개의 친구 관계 쌍 (a b) 형태로 제공되며, 이는 a와 b가 친구임을 의미한다.
  • 네 번째 줄: 특정 인원 X (1 ≤ X ≤ N) – 친구 관계를 확인할 인원

출력 형식

입력된 인원 X의 친구가 아닌 사람의 수를 출력하시오.

예제 입력

    5
    4
    1 2
    1 3
    2 4
    4 5
    1
    

예제 출력

    3
    

문제 풀이 과정

1단계: 문제 이해 및 분석

주어진 문제를 이해하기 위해서는 입력으로 제공되는 친구 관계를 그래프로 표현할 수 있어야 합니다. 이를 위해 인접 리스트를 사용하기로 합니다. 이 방법을 통해 각 인원과 그들의 친구를 연결하여 관계를 쉽게 파악할 수 있습니다.

2단계: 데이터 구조 설계

각각의 인원은 배열의 인덱스를 통해 친구 관계를 저장할 수 있습니다. 예를 들어, 인원 1과 친구인 인원을 저장하기 위해 인접 리스트에 상대 인원의 번호를 추가합니다. 이 구조를 사용하면 특정 인원의 친구를 쉽게 찾을 수 있습니다.

3단계: 알고리즘 설계

친구가 아닌 사람의 수를 계산하기 위해 다음과 같은 절차를 따릅니다:

  1. 모든 인원(1부터 N까지)과 친구 관계를 확인하여 친구 리스트를 생성합니다.
  2. 특정 인원 X의 친구 리스트를 참조하여 친구가 아닌 사람의 수를 계산합니다.
  3. 최종적으로 friendCount 변수를 선언하고, 인원 수에서 X와 X의 친구 수를 빼면 친구가 아닌 사람의 수를 얻을 수 있습니다.

4단계: 자바스크립트 구현


    function countNonFriends(N, M, relations, X) {
        // 인접 리스트 생성
        const friends = Array.from({ length: N + 1 }, () => []);

        // 관계 추가
        relations.forEach(([a, b]) => {
            friends[a].push(b);
            friends[b].push(a);
        });

        // 친구가 아닌 인원 수 세기
        const friendSet = new Set(friends[X]);
        let count = 0;

        for (let i = 1; i <= N; i++) {
            if (i !== X && !friendSet.has(i)) {
                count++;
            }
        }

        return count;
    }
    
    const N = 5;
    const M = 4;
    const relations = [[1, 2], [1, 3], [2, 4], [4, 5]];
    const X = 1;
    console.log(countNonFriends(N, M, relations, X)); // 3
    

5단계: 시간 복잡도 분석

이 알고리즘의 시간 복잡도는 각각의 친구 관계를 확인하고 세는 과정에서 O(N + M)의 복잡도를 가집니다. 이는 각 관계를 한 번씩만 탐색하기 때문에 효율적입니다.

결론

이 문제를 통해 그래프 관련 문제를 푸는 과정과 친구 관계를 파악하는 방법을 배울 수 있습니다. 또한, 자바스크립트의 배열과 객체를 활용하여 데이터를 관리하고, 알고리즘을 구현하는 연습을 할 수 있습니다. 코딩테스트 준비 시, 이러한 문제 유형을 여러 번 풀어보는 것이 중요합니다.

자바스크립트 코딩테스트 강좌, 이친수 구하기

본 글에서는 자바스크립트로 이친수를 구하는 알고리즘 문제를 다루겠습니다. 이친수는 중복 괄호와 같은
구조적 개념과 관련된 수학적 개념으로, 이 문제는 프로그래밍 면접에서 종종 등장합니다.
따라서 이 문제를 확실히 이해하고 풀 수 있는 방법을 찾아보겠습니다.

이친수란?

이친수는 0과 1로 구성된 길이 N의 문자열 중에서 다음의 규칙을 따르는 것들입니다:

  • 문자열의 첫 번째와 마지막 문자는 0이어야 한다.
  • 문자열 내 1의 개수는 항상 1개 이상이어야 하며, 연속된 1은 없으며, 각 1은 반드시 0으로 둘러싸여 있어야 한다.

예를 들어, 길이 5의 이친수는 00000, 01000, 00100, 00010, 00001,
01010, 01100, 10000 등이 있습니다. 이친수는 피보나치 수열과 같으며,
N 길이에 따라 다른 개수를 받을 수 있습니다.

문제 설명

자연수 N이 주어질 때, 길이가 N인 이친수의 개수를 출력하는 문제입니다.
예를 들어, N = 5일 경우, 이친수의 개수를 구해야 하며,
그 결과는 8이어야 합니다.

해법

이 친수를 구하기 위해 재귀 호출이나 다이나믹 프로그래밍(DP) 방법을 사용할 수 있습니다.
아래는 이친수를 구하는 공식입니다.

  • p(n) = p(n-1) + p(n-2) (n ≥ 2, p(0) = 1, p(1) = 1)

이 공식은 이친수를 재귀적으로 계산하는 방법입니다.
주의할 점은 n이 0일 때 1을 반환해야 한다는 점입니다.
또한, p(n-1)과 p(n-2)의 관계를 통해 이전 이친수 개수를 의미합니다.

알고리즘 구현

        
            // 자바스크립트로 이친수를 만드는 함수입니다.
            function countCatalanNumbers(n) {
                // 이친수를 저장할 배열
                const dp = new Array(n + 1).fill(0);
                dp[0] = 1; // 길이 0인 경우
                dp[1] = 1; // 길이 1인 경우

                // 다이나믹 프로그래밍을 사용해 이친수를 계산합니다.
                for (let i = 2; i <= n; i++) {
                    dp[i] = dp[i - 1] + dp[i - 2];
                }

                return dp[n]; // n 길이의 이친수 개수를 반환합니다.
            }

            // 함수 호출 예시
            const n = 5; // N 값
            console.log(`길이 ${n}의 이친수 개수는: ${countCatalanNumbers(n)}`);
        
        

진행 과정 설명

  1. 문제 이해하기: 자연수 N에 대해 이친수를 구하는 문제입니다.
  2. 다이나믹 프로그래밍 접근: 이친수를 구조적으로 정의합니다.
  3. 배열 초기화: dp 배열을 생성하여 기본 값을 설정합니다.
  4. 반복문 실행: 이친수의 개수를 배열에 저장하며 계산합니다.
  5. 결과 검증: 함수 출력으로 결과가 올바른지 검증합니다.

실행 결과

        
            // 입력: N = 5
            // 출력: 길이 5의 이친수 개수는: 8
        
    

결론

이 친수를 구하는 방법에 대해 알아보았으며, 다이나믹 프로그래밍을 통해 효율적으로 문제를 해결할 수 있었습니다.
이 문제는 프로그래밍 인터뷰에서 자주 출제되므로 알고리즘의 원리를 이해하고 구현할 수 있는 능력을 기르는 것이 중요합니다.

자바스크립트 코딩테스트 강좌, 특정 거리의 도시 찾기

안녕하세요, 여러분! 오늘은 자바스크립트를 사용하여 특정 거리에 있는 도시를 찾는 알고리즘 문제에 대해 다루어보겠습니다. 이 문제는 코딩 테스트에서 자주 출제되는 주제 중 하나로, 그래프 탐색 및 BFS(너비 우선 탐색) 기법을 응용하는 방법을 배우게 될 것입니다.

문제 설명

주어진 두 정점으로부터 시작하여 특정 거리만큼 떨어진 도시들의 리스트를 반환하는 함수를 작성하세요. 도시는 간선으로 연결되어 있으며, 거리 계산은 각 간선이 1로 동일하다고 가정합니다.

입력

  • n: 도시의 개수 (1 ≤ n ≤ 300,000)
  • edges: 각 도시를 연결하는 간선들, 이것은 2차원 배열로 주어집니다. edges[i] = [a, b]는 도시 a와 도시 b가 직접 연결되어 있다는 것을 의미합니다.
  • start: 평균적으로 거리 계산을 시작할 도시 (1 ≤ start ≤ n)
  • distance: 특정 거리 k (0 ≤ distance ≤ n)

출력

특정 거리만큼 떨어진 도시들의 배열을 오름차순으로 정렬하여 반환하십시오. 만약 그러한 도리가 없다면 빈 배열을 반환합니다.

문제 해결 전략

이 문제의 핵심은 BFS 알고리즘을 이용하여 그래프를 탐색하는 것입니다. BFS는 그래프의 모든 정점을 탐색할 수 있는 기법으로, 최단 경로를 찾는 데 적합합니다.

문제를 해결하기 위한 기본 단계는 다음과 같습니다:

  1. 주어진 edges 배열을 통해 그래프 구조를 정의합니다.
  2. BFS를 통해 주어진 start 도시에서 각 도시까지의 거리를 계산합니다.
  3. 거리 값이 특정 거리와 일치하는 도시들을 수집합니다.
  4. 결과 도시 리스트를 오름차순으로 정렬하여 반환합니다.

구현 단계

1단계: 그래프 구조화

도시와 도시 간의 연결 정보를 담기 위해 인접 리스트를 사용할 것입니다. 이는 각 도시를 키로 하고 연결된 도시의 리스트를 값으로 갖는 객체로 구성됩니다.

2단계: BFS 알고리즘 구현

BFS를 통해 시작 도시로부터 각 도시까지의 거리를 계산하고, 특정 거리에 도달할 수 있는 도시를 찾아냅니다.

3단계: 결과 처리 및 반환

특정 거리와 일치하는 도시들을 수집하여 정렬한 후 반환합니다.

자바스크립트 코드 구현


function findCitiesAtDistance(n, edges, start, distance) {
    // Step 1: 그래프 생성
    const graph = Array.from({ length: n + 1 }, () => []);
    for (const [a, b] of edges) {
        graph[a].push(b);
        graph[b].push(a); // 양방향 그래프이므로 양쪽 모두 추가
    }
    
    // Step 2: BFS를 위한 변수 설정
    const queue = [];
    const distances = Array(n + 1).fill(-1); // 거리 초기화
    distances[start] = 0;
    queue.push(start);
    
    // BFS 탐색 수행
    while (queue.length > 0) {
        const currentCity = queue.shift();
        
        for (const neighbor of graph[currentCity]) {
            // 아직 방문하지 않은 도시인 경우
            if (distances[neighbor] === -1) {
                distances[neighbor] = distances[currentCity] + 1;
                queue.push(neighbor);
            }
        }
    }
    
    // Step 3: 특정 거리에 있는 도시 찾기
    const result = [];
    for (let city = 1; city <= n; city++) {
        if (distances[city] === distance) {
            result.push(city);
        }
    }

    // 오름차순으로 정렬
    result.sort((a, b) => a - b);
    return result;
}
    

코드 설명

위의 코드는 주어진 요구사항에 맞춰 특정 거리의 도시를 찾는 함수입니다. 각 단계에 대해 설명하겠습니다:

그래프 생성

edges 배열을 순회하며, 각 도시 간의 연결 정보를 그래프 구조로 만들었습니다. 이때, 인접 리스트를 사용하여 각 도시가 연결된 도시 리스트를 보관합니다.

BFS 구현

BFS를 사용하여 시작 도시로부터의 거리 값을 계산하는 과정입니다. 각 도시의 거리를 기록하기 위해 distances 배열을 사용하며, 방문한 도시는 -1로 표시하여 중복 처리를 방지합니다.

결과 처리

모든 도시를 탐색한 후, 특정 거리와 일치하는 도시를 결과 리스트에 추가하고, 최종적으로 오름차순으로 정렬한 후 반환합니다.

테스트 케이스

이제 몇 가지 테스트 케이스를 통해 구현된 코드의 동작을 확인해 보겠습니다.


console.log(findCitiesAtDistance(6, [[3, 6], [4, 3], [3, 2], [1, 3], [1, 2], [2, 4]], 5, 2)); 
// 출력: [4, 5, 6]
console.log(findCitiesAtDistance(4, [[1, 2], [1, 3], [2, 4]], 1, 2)); 
// 출력: [4]
console.log(findCitiesAtDistance(5, [[1, 2], [1, 3], [1, 4], [2, 5]], 1, 1)); 
// 출력: [2, 3, 4]
console.log(findCitiesAtDistance(7, [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]], 1, 3)); 
// 출력: [4]
console.log(findCitiesAtDistance(3, [], 1, 1)); 
// 출력: []
    

결론

이번 글에서는 특정 거리의 도시를 찾는 알고리즘 문제를 다루며, BFS를 활용한 그래프 탐색의 기본 원리를 설명했습니다. 이 문제를 통해 그래프 구조화, BFS 구현, 결과 처리 등 여러가지를 배울 수 있었습니다. 이러한 문제는 코딩 테스트에서 자주 출제되므로 이해하고 연습하는 것이 중요합니다. 다음 시간에는 더 복잡한 그래프 문제를 다루도록 하겠습니다. 감사합니다!

자바스크립트 코딩테스트 강좌, 기하 알아보기

코딩 테스트는 요즘 많은 기업에서 필수적으로 진행하는 과정입니다. 특히 자바스크립트는 웹 개발에서 많이 사용되는 프로그래밍 언어로, 기하학적 문제를 통해 알고리즘에 대한 이해도를 높이는 데 큰 도움이 됩니다. 이번 글에서는 자바스크립트로 해결할 수 있는 기하학적 알고리즘 문제를 소개하고, 그 풀이 과정을 자세히 설명하겠습니다.

문제 설명

다음은 직사각형이 주어진 경우, 두 개의 점이 이 직사각형 내부에 있는지를 판단하는 문제입니다.

문제: 직사각형 내부 점 판별하기

주어진 직사각형의 좌측 하단 꼭지점의 좌표는 (x1, y1)이고, 우측 상단 꼭지점의 좌표는 (x2, y2)입니다. 또한 두 개의 점 A(xA, yA)와 B(xB, yB)가 있을 때, 이 점들이 직사각형 내부에 있는지를 판별하는 함수를 작성하세요.

입력

  • 직사각형의 좌측 하단 꼭지점: (x1, y1)
  • 직사각형의 우측 상단 꼭지점: (x2, y2)
  • 점 A: (xA, yA)
  • 점 B: (xB, yB)

출력

각 점이 직사각형 내부에 있는 경우 true를, 아닌 경우 false를 반환하는 함수를 작성하세요. 두 점 모두 내부에 있을 경우 true, 그 외의 경우 false를 반환합니다.

풀이 과정

이제 이 문제를 해결하는 방법을 단계별로 알아보겠습니다.

1단계: 문제 이해하기

우리는 주어진 직사각형의 꼭지점 좌표를 가지고 있고, 각 점의 좌표를 확인해야 합니다. 직사각형 내부의 조건은 다음과 같습니다:

  • x1 < xA < x2
  • y1 < yA < y2
  • x1 < xB < x2
  • y1 < yB < y2

위 조건을 모두 만족해야 각 점은 직사각형 내부에 존재해야 합니다.

2단계: 함수 작성하기

다음은 이를 바탕으로 작성한 자바스크립트 코드입니다.


function isPointInsideRectangle(x1, y1, x2, y2, xA, yA, xB, yB) {
    const isAInside = (x1 < xA && xA < x2) && (y1 < yA && yA < y2);
    const isBInside = (x1 < xB && xB < x2) && (y1 < yB && yB < y2);
    
    return isAInside && isBInside;
}

// 테스트
const result = isPointInsideRectangle(0, 0, 10, 10, 5, 5, 5, 5); // true
console.log(result);
    

3단계: 테스트 및 검증

이제 함수를 테스트해봅시다. 우리는 직사각형의 좌측 하단 꼭지점이 (0,0)이고 우측 상단 꼭지점이 (10,10)인 경우, (5,5)라는 점이 내부에 있는지 확인했습니다.

위의 예시에서는 두 점이 동일한 (5,5)이므로 함수는 true를 반환합니다. 그러나 한 점이 직사각형 외부에 있을 경우 false를 반환해야 합니다.

4단계: 다양한 케이스 확인하기

우리는 여러 가지 케이스를 통해 함수를 검증할 수 있습니다. 다음은 추가적인 테스트 예시입니다.


// 케이스 1: 두 점 모두 내부
console.log(isPointInsideRectangle(0, 0, 10, 10, 1, 1, 2, 2)); // true

// 케이스 2: 하나의 점만 내부
console.log(isPointInsideRectangle(0, 0, 10, 10, 1, 1, 11, 11)); // false

// 케이스 3: 두 점 모두 외부
console.log(isPointInsideRectangle(0, 0, 10, 10, -1, -1, 11, 11)); // false

// 케이스 4: 직사각형의 경계에 위치
console.log(isPointInsideRectangle(0, 0, 10, 10, 0, 5, 5, 10)); // false
    

마무리

이제 우리는 자바스크립트를 사용하여 주어진 직사각형 내부에 점들이 있는지를 판별하는 함수를 완성했습니다. 이와 같은 기하 문제는 알고리즘적 사고를 기르는 데 큰 도움이 되며, 코딩 테스트에서 빈번하게 출제되는 유형이기도 합니다.

이 글을 통해 기하 문제의 기본적인 이해와 적용 방법을 익히셨기를 바랍니다. 앞으로도 다양한 알고리즘 문제에 도전해 보시기 바랍니다!

자바스크립트 코딩테스트 강좌, 최장 공통 부분 수열 찾기

문제 설명

두 개의 문자열이 주어졌을 때, 이 두 문자열의 최장 공통 부분 수열(Longest Common Subsequence, LCS)을 찾는 문제입니다.
최장 공통 부분 수열은 두 문자열의 순서를 유지하면서 겹치는 최대 길이의 부분 문자열을 의미합니다.
예를 들어, 문자열 A가 “ABCBDAB”이고 문자열 B가 “BDCAB”일 경우, 최장 공통 부분 수열은 “BDAB” 또는 “BCAB” 등입니다.

입력 형식

– 첫 번째 줄에 문자열 A의 길이 N과 문자열 B의 길이 M이 주어집니다. (1 ≤ N, M ≤ 1000)
– 두 번째 줄에 문자열 A가 주어집니다.
– 세 번째 줄에 문자열 B가 주어집니다.

출력 형식

– 두 문자열의 최장 공통 부분 수열의 길이를 출력합니다.

예제

            입력:
            7 5
            ABCBDAB
            BDCAB

            출력:
            4
        

문제 해결을 위한 접근법

이 문제는 동적 프로그래밍(Dynamic Programming)의 전형적인 예시입니다.
LCS를 구하기 위해서는 두개의 문자열을 비교하여 일치하는 문자를 찾고,
이 때의 부분 문제를 해결하여 최종 길이를 도출할 수 있습니다.

단계별 접근

  1. 동적 계획법 테이블 초기화:

    2차원 배열 DP를 생성합니다. DP[i][j]는 문자열 A의 처음 i개 문자와 문자열 B의 처음 j개 문자까지의
    최장 공통 부분 수열의 길이를 저장합니다. 배열의 크기는 (N+1) x (M+1)입니다.

  2. 테이블 채우기:

    A의 i번째 문자와 B의 j번째 문자가 같으면 DP[i][j] = DP[i-1][j-1] + 1
    그렇지 않다면 DP[i][j] = max(DP[i-1][j], DP[i][j-1])로 설정합니다.

  3. 결과 출력:

    DP[N][M]에 도달하면 최장 공통 부분 수열의 길이를 반환할 수 있습니다.

자바스크립트 코드


function longestCommonSubsequence(A, B) {
    const N = A.length;
    const M = B.length;
    
    // DP 테이블 초기화
    const DP = Array.from(Array(N + 1), () => Array(M + 1).fill(0));
    
    // DP 테이블 채우기
    for (let i = 1; i <= N; i++) {
        for (let j = 1; j <= M; j++) {
            if (A[i - 1] === B[j - 1]) {
                DP[i][j] = DP[i - 1][j - 1] + 1;
            } else {
                DP[i][j] = Math.max(DP[i - 1][j], DP[i][j - 1]);
            }
        }
    }
    
    return DP[N][M];
}

// 입력 예제 실행
const A = 'ABCBDAB';
const B = 'BDCAB';
console.log(longestCommonSubsequence(A, B)); // Output: 4
        

복습 및 연습 문제

이 문제를 완전히 이해했다면, 추가적인 연습문제를 통해 능력을 키워보세요. 다음과 같은 문제에 도전해 보십시오.

  • 주어진 두 문자열 대신 세 개의 문자열에서 최장 공통 부분 수열을 찾는 문제.
  • 대소문자를 구분하지 않고 최장 공통 부분 수열을 찾는 문제.
  • 최장 공통 부분 수열을 구하는 모든 가능한 조합을 출력하는 문제.

맺음말

최장 공통 부분 수열 문제는 컴퓨터 과학의 중요한 개념 중 하나로, 다양한 알고리즘 문제에 응용될 수 있습니다.
동적 계획법을 사용한 이 방식을 통해 문제를 해결하는 것은 더욱 복잡한 문제를 해결하는 데 도움이 될 것입니다. 다양한 문제를 풀며 실력을 다져 보세요!