BOJ 16360번 Go Latin 문제

이번 ICPC 본선 문제 중에 유일하게 푼 문제이다. 내가 푼게 아니라서 집에 와서 풀어봤다.

if문으로 각 조건을 비교하고 테이블에 맞게 붙여주거나 수정 후 붙여주면 된다.

테이블에 속하지 않으면 us를 붙인다.

16360.cpp

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    while (n--) {
        string s;
        cin >> s;
        int sSize = s.size();

        if (s[sSize - 1] == 'a') {
            s += "s";
        } else if (s[sSize - 1] == 'i' || s[sSize - 1] == 'y') {
            s[sSize - 1] = 'i';
            s += "os";
        } else if (s[sSize - 1] == 'l') {
            s += "es";
        } else if (s[sSize - 1] == 'n') {
            s[sSize - 1] = 'a';
            s += "nes";
        } else if (s[sSize - 1] == 'e' && s[sSize - 2] == 'n') {
            s[sSize - 2] = 'a';
            s[sSize - 1] = 'n';
            s += "es";
        } else if (s[sSize - 1] == 'o') {
            s += 's';
        } else if (s[sSize - 1] == 'r') {
            s += "es";
        } else if (s[sSize - 1] == 't') {
            s += "as";
        } else if (s[sSize - 1] == 'u') {
            s += "s";
        } else if (s[sSize - 1] == 'v') {
            s += "es";
        } else if (s[sSize - 1] == 'w') {
            s += "as";
        } else {
            s += "us";
        }
        cout << s << '\n';
    }
}

'알고리즘 & SQL > 백준(BOJ)' 카테고리의 다른 글

백준 2331번 : 반복수열 C++  (0) 2018.11.06
백준 12761번 : 돌다리 C++  (0) 2018.11.06
백준 14753번 : MultiMax C++  (0) 2018.11.02
백준 9086번 : 문자열 C++  (0) 2018.11.02
백준 1427번 : 소트인사이드 C++  (0) 2018.11.02

BOJ 14753번 MultiMax 문제

작년 ACM-ICPC 인터넷 예선 문제였다. 올해 ICPC 본선 예비소집 B번 문제로 나왔다.

오름차순으로 정렬을 하고 맨 뒤 가장 큰 숫자 두 개를 골라 곱한 수와 세 개를 골라 곱한 수 중 큰 값을 일단 max로 갖고 있는다.

음수가 두 개 이상 나오는 경우 맨 앞 [0] [1]을 곱한 수도 양수이기 때문에 이 둘을 곱한 수와 현재 max 중 큰 값을 갖고 있는다.

또 위 음수를 곱한 수와 양수로 가장 큰 수 [size-1]를 곱한 수랑 현재 max를 비교해서 더 높은 값을 출력하면 된다.

14753.cpp

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    vector<int> v;
    for (int i = 0; i < n; i++) {
        int input;
        cin >> input;
        v.push_back(input);
    }
    sort(v.begin(), v.end());
    int result = max(v[n - 1] * v[n - 2], v[n - 1] * v[n - 2] * v[n - 3]);
    if (v[0] * v[1] > 0) {
        result = max(v[0] * v[1], result);
        result = max(v[0] * v[1] * v[n - 1], result);
    }
    cout << result;
}

정렬 알고리즘의 실행시간 비교

  • Exchange sort, Merge sort, Quick sort 알고리즘을 구현하기.

  • 각각의 정렬 방법에서 key를 비교한 횟수와 실행시간을 측정하여 비교한다. 측정에는 clock 함수를 쓴다.

  • Exchange sort와 Quick sort의 비교는 key의 갯수가 다른 3가지 오름차순으로 정렬된 데이터를 생성해여 비교한다.

  • Merge sort와 Quick sort의 비교는 key의 갯수가 다른 3가지 경우에 대해 각각 5개의 임의의 데이터를 생성하여 평균값으로 비교한다.

  • key의 갯수는 실행시간이 충분한 유효숫자를 가질 수 있도록 각자 정한다.

  • 측정된 key의 비교횟수와 실행시간이 정렬 알고리즘들의 이론적 시간 복잡도와 일치하는지 분석한다.

  • 입력 형식
    input.txt, 처음은 오름차순 데이터, 그 다음은 임의의 데이터가 입력된다.

  • 출력 형식

    Image

  • Exchange Sort : for문을 중첩하여 선택된 인덱스의 키와 나머지 키를 비교하여 선택된 키보다 작으면 앞으로 가게 한다.(인접한 원소끼리 비교하여 작은 게 앞으로 오게 한다.) 시간 복잡도가 O(N^2)이다.

  • Merge Sort : 정렬되지 않은 배열을 반으로 나눈다. 길이가 1이 될 때 까지 나눈 후, 나눈 것을 다시 합친다. 합칠 때 작은 원소 순서대로 오게 한다. 시간 복잡도가 O(NlogN)이다.

  • Quick Sort : 한 원소를 pivot으로 잡는다. 배열의 맨 왼쪽 원소를 left, 오른쪽 인덱스를 right라고 하고, left부터 오른쪽으로 옮겨가며 pivot보다 큰 값이 나올때까지, right부터 왼쪽으로 옮겨가며 pivot보다 작은 값이 나올때까지 이동한다. 두 원소를 교환한다. left가 right보다 오른쪽에 있으면 다시 왼쪽 오른쪽으로 나눠진 배열을 다시 퀵 정렬한다. 시간 복잡도가 최악의 경우에 O(N^2), 평균 O(NlogN)이 나온다.

Exchange Sort와 Quick Sort의 비교 (오름차순으로 정렬된 데이터)

  • N값(key의 개수)에 10000, 20000, 40000을 넣어 수행한다.
    Image

  • Exchange sort의 경우 이론적 시간 복잡도가 O(N^2) 이므로 N이 2배 늘어날때마다 시간이 4배 늘어날 것으로 예상이 된다.

    N=10000 일때 0.09375, N=20000일 때 0.359375, N=40000일 때 1.515625가 걸렸다.

    0.09375 : 0.359375 = 1 : 3.83333 이므로 거의 1:4 이고, 0.09375 : 1.515625= 1:16.1666667 이므로 거의 1:16이다.

    0.359375 : 1.515625= 1 : 4.217391 로 거의 1:4이다.

    clock의 오차를 감안하면 exchange sort의 시간 복잡도가 O(N^2)인 것을 알 수 있다. 이론적 시간 복잡도와 일치한다.

    key 값의 비교 횟수도 역시 49995000: 199990000 : 799980000 = 1 : 4 : 16의 꼴을 띈다.

  • Quick Sort는 정렬된 데이터가 들어갔을 때 최악의 경우로 O(N^2)이 걸린다.

    그러므로 N값이 2배 늘어날때마다 시간이 4배 늘어날 것으로 예상이 된다.

    N=10000일 때 0.078125, N=20000일 때 0.328125, N=40000일 때 1.3125가 걸렸다.

    0.078125 : 0.328125 = 1 : 4.2 로 거의 1:4 이고, 0.078125 : 1.3125 = 1 : 16.8 로 거의 1:16이다.

    0.328125 : 1.3125 = 1 : 4이다.

    clock의 오차를 감안하면 Quick Sort는 정렬된 데이터가 들어갔을 때 최악으로 O(N^2)이 걸린다는 것을 알 수 있다.

    key 값의 비교 횟수도 역시 49995000: 199990000 : 799980000 = 1 : 4 : 16의 꼴을 띈다.

    (N)^2: (2N)^2 : (4N)^2 = 1 : 4 : 16

Merge Sort와 Quick Sort의 비교 (무작위 데이터, 5번 수행 후 평균값)

  • N값(key의 개수)이 1000000, 2000000, 4000000을 넣어 수행한다.
    Image

  • Merge Sort의 경우 이론적 시간 복잡도가 O(NlogN)이다. N값이 2배 늘어날 때 마다 약 2.~배 정도 늘어날 것으로 예상이 된다.

    N=1000000일 때 0.23125, N=2000000일 때 0.48125, N=4000000일 때 0.95625가 걸렸다.

    0.23125 : 0.48125 = 1 : 2.081081, 0.23125 : 0.95625 = 1 : 4.135135, 0.48125 : 0.95625 = 1 : 1.987013 으로, clock의 오차를 감안하면 예상된 시간 복잡도와 비슷하다.

    key 값의 비교 횟수는 19951424 : 41902848 : 87805696 = 1 : 2.1 : 4.4 로 2배 보다 약간 더 늘어났다.

  • Quick Sort의 경우 평균적으로 O(NlogN)의 시간 복잡도를 가진다. N값이 2배 늘어날때마다 2.~배 늘어날 것으로 예상이 된다.

    N=1000000일 때 0.031250, N=2000000일 때 0.065625, N=4000000일 때 0.131250가 걸렸다.

    0.031250 : 0.065625 = 1 : 2.1, 0.065625 : 0.131250 = 1 : 2, 0.031250 : 0.13125 = 1 : 4.2 이므로 clock의 오차와 평균을 구할 때 5번 밖에 수행하지 않아 오차가 클 수 있다는 점을 감안하면 예상된 시간 복잡도와 일치한다.

    key 값의 비교 횟수는 4088134 : 8475511 : 17790888 = 1 : 2.07319 : 4.351835로 N값이 2배 늘어날 때마다 2배보다 약간 더 늘어났다.

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <vector>
using namespace std;
char ex[] = "Exchange Sort";  // 13
char qu[] = "Quick Sort";     // 10
char me[] = "Merge Sort";     // 10
char kc[] = "Key Compares";   // 12
char et[] = "Exe.Time";       // 8
char sp[] = "             ";  // 13

unsigned long long key_compare; // 비교횟수 count
unsigned long long result[2][3];  // 1번 key_compare 저장
unsigned long long result2[2][3];  // 2번 key_compare 저장
double ti[2][3];   // 1번 시간 저장
double ti2[2][3];   // 2번 시간 저장

int in[3];         // 1번 N 값 저장
int in2[3];         // 2번 N 값 저장

void init() { key_compare = 0; }
void exchange_sort(unsigned long long * v, int size);
void merge(unsigned long long * v, int low, int mid, int high);
void mergesort(unsigned long long * v, int low, int high);
void quick_sort(unsigned long long *v, int left, int right);

int main() {
    int n;
    ifstream ifs("input.txt");

    // 1번
    // Exchange Sort, Quick Sort 비교, 오름차순 정렬
    for (int i = 0; i < 3; i++) {
        ifs >> n;
        in[i] = n;

        unsigned long long * ev = new unsigned long long[n];
        unsigned long long * qv = new unsigned long long[n];
        for (int j = 0; j < n; j++) {
            ev[j] = qv[j] = j;
        }
        // Exchange Sort
        init(); // key_compare 초기화
        clock_t t = clock();
        exchange_sort(ev, n);
        t = clock() - t; // 시간 저장
        unsigned long long es_key = key_compare;
        double es_time = (double)(t) / CLOCKS_PER_SEC;
        // Quick Sort
        init(); // key compare 초기화
        t = clock();
        quick_sort(qv, 0, n - 1);
        t = clock() - t; // 시간 저장
        unsigned long long qs_key = key_compare;
        double qs_time = (double)(t) / CLOCKS_PER_SEC;

        result[0][i] = es_key;
        result[1][i] = qs_key;
        ti[0][i] = es_time;
        ti[1][i] = qs_time;

        delete ev, qv;
    }

    // 2번
    // Merge Sort, Quick Sort 비교, 랜덤
    srand((unsigned int)time(0));
    for (int i = 0; i < 3; i++) {
        ifs >> n;
        in2[i] = n; // case N 저장

        unsigned long long * mv = new unsigned long long[n+1];
        unsigned long long * qv = new unsigned long long[n+1];

        unsigned long long kc_ms = 0;     // key compares of merge
        unsigned long long kc_qs = 0;     // key compares of quick
        double et_ms = 0;  // ex.time of merge
        double et_qs = 0;  // ex.time of quick

        // Random Number
        for (int k = 0; k < 5; k++) {
            for (int j = 0; j < n; j++) {
                unsigned long long push_num = (unsigned long long)rand() % RAND_MAX;
                mv[j] = qv[j] = push_num;
            }

            // mergesort
            init();  // key_compare 초기화
            clock_t t = clock();
            mergesort(mv, 0, n - 1);  // 실행
            t = clock() - t;
            kc_ms += key_compare;
            et_ms += (double)(t) / CLOCKS_PER_SEC;  // 경과 시간 저장

            // quicksort
            init();  // key_compare 초기화
            t = clock();
            quick_sort(qv, 0, n - 1);  // 실행
            t = clock() - t;
            kc_qs = key_compare;
            et_qs = (double)(t) / CLOCKS_PER_SEC;  // 경과 시간 저장


        }

        kc_ms /= 5;
        kc_qs /= 5;
        et_ms /= 5.0;
        et_qs /= 5.0;

        result2[0][i] = kc_ms;
        result2[1][i] = kc_qs;
        ti2[0][i] = et_ms;
        ti2[1][i] = et_qs;

        delete mv, qv;
    }
    //                                    N = Case1    N = Case 2    N = Case 3
    printf("%-14s\t %14s\t N=%-10d\t N=%-10d\t N=%-10d\n", sp, sp, in[0], in[1], in[2]);
    // Exchange Sort    Key Compares
    //                    Exe.Time
    printf("%-14s\t %-14s\t %-12llu\t %-12llu\t %-12llu\t\t\n", ex, kc, result[0][0], result[0][1], result[0][2]);
    printf("%-14s\t %-14s\t %-12lf\t %-12lf\t %-12lf\t\t\n", sp, et, ti[0][0], ti[0][1], ti[0][2]);
    // Quick Sort    Key Compares
    //                Exe.Time
    printf("%-14s\t %-14s\t %-12llu\t %-12llu\t %-12llu\t\t\n", qu, kc, result[1][0], result[1][1], result[1][2]);
    printf("%-14s\t %-14s\t %-12lf\t %-12lf\t %-12lf\t\t\n", sp, et, ti[1][0], ti[1][1], ti[1][2]);
    printf("\n\n");

    //                                    N = Case1    N = Case 2    N = Case 3
    printf("%-14s\t %14s\t N=%-10d\t N=%-10d\t N=%-10d\n", sp, sp, in2[0], in2[1], in2[2]);
    // Merge Sort    Key Compares
    //                    Exe.Time
    printf("%-14s\t %-14s\t %-12llu\t %-12llu\t %-12llu\t\t\n", me, kc, result2[0][0], result2[0][1], result2[0][2]);
    printf("%-14s\t %-14s\t %-12lf\t %-12lf\t %-12lf\t\t\n", sp, et, ti2[0][0], ti2[0][1], ti2[0][2]);
    // Quick Sort    Key Compares
    //                Exe.Time
    printf("%-14s\t %-14s\t %-12llu\t %-12llu\t %-12llu\t\t\n", qu, kc, result2[1][0],    result2[1][1], result2[1][2]);
    printf("%-14s\t %-14s\t %-12lf\t %-12lf\t %-12lf\t\t\n", sp, et, ti2[1][0],    ti2[1][1], ti2[1][2]);
}

void exchange_sort(unsigned long long * v, int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = i + 1; j < size; j++) {
            key_compare++;
            if (v[i] > v[j]) {
                unsigned long long temp = v[i];
                v[i] = v[j];
                v[j] = temp;
            }
        }
    }
}

void merge(unsigned long long * v, int low, int mid, int high) {
    int i, j, k;
    i = low;      // 왼쪽 시작
    j = mid + 1;  // 오른쪽 시작
    k = low;      // 결과 배열 인덱스
    unsigned long long *temp = new unsigned long long[high + 1];
    while (i <= mid && j <= high) {
        if (v[i] < v[j]) {
            key_compare++;
            temp[k] = v[i];
            i++;
        }
        else {
            key_compare++;
            temp[k] = v[j];
            j++;
        }
        k++;
    }
    while (i <= mid) {
        key_compare++;
        temp[k] = v[i];
        i++;
        k++;
    }

    while (j <= high) {
        key_compare++;
        temp[k] = v[j];
        j++;
        k++;
    }
    for (int i = low; i <= high; i++) {
        v[i] = temp[i];
    }
    delete temp;
}
void mergesort(unsigned long long * v, int low, int high) {
    int mid;
    if (low < high) {
        mid = (low + high) / 2;
        mergesort(v, low, mid);
        mergesort(v, mid + 1, high);
        merge(v, low, mid, high);
    }
}

void quick_sort(unsigned long long * v, int left, int right) {
    int i = left, j = right;
    unsigned long long pivot = v[left];
    do {
        while (v[i] < pivot) {
            key_compare++;
            i++;
        }
        while (v[j] > pivot) {
            key_compare++;
            j--;
        }
        if (i <= j) {
            if (v[i] > v[j]) {
                unsigned long long temp = v[i];
                v[i] = v[j];
                v[j] = temp;
            }
            i++;
            j--;
        }
    } while (i <= j);
    if (left < j) {
        quick_sort(v, left, j);
    }
    if (i < right) {
        quick_sort(v, i, right);
    }
}

BOJ 1427번 소트인사이드 문제

sort를 사용해서 쉽게 풀 수 있는 문제였다.

그냥 쓸 줄만 알면 풀수 있다.

1427.cpp

#include <bits/stdc++.h>
using namespace std;
int main() {
    string s;
    cin >> s;
    sort(s.begin(), s.end());
    reverse(s.begin(), s.end());
    cout << s;
}

'알고리즘 & SQL > 백준(BOJ)' 카테고리의 다른 글

백준 14753번 : MultiMax C++  (0) 2018.11.02
백준 9086번 : 문자열 C++  (0) 2018.11.02
백준 2851번 : 슈퍼 마리오 C++  (1) 2018.11.02
백준 2998번 : 8진수 C++  (0) 2018.10.31
백준 10987번 : 단위 C++  (0) 2018.10.30

Visual Studio Code에서 <bits/stdc++.h> 헤더 파일을 사용하는 방법

  • MinGW를 설치했을경우

    • C:\MinGW\lib\gcc\mingw32\6.3.0\include\c++\mingw32\bits 폴더를 C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include에 복사하면 쓸 수 있다.
    • 위 경로는 사용자에 따라 달라질 수 있으니 참고만 하자.
  • MinGW를 설치하지 않았을 경우

    • C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include에 들어가서 bits 폴더를 생성하고, stdc++.h 파일을 만든다.

    • 아래를 복사해서 입력한다.

      // C++ includes used for precompiling -*- C++ -*-
      
      // Copyright (C) 2003-2013 Free Software Foundation, Inc.
      //
      // This file is part of the GNU ISO C++ Library.  This library is free
      // software; you can redistribute it and/or modify it under the
      // terms of the GNU General Public License as published by the
      // Free Software Foundation; either version 3, or (at your option)
      // any later version.
      
      // This library is distributed in the hope that it will be useful,
      // but WITHOUT ANY WARRANTY; without even the implied warranty of
      // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      // GNU General Public License for more details.
      
      // Under Section 7 of GPL version 3, you are granted additional
      // permissions described in the GCC Runtime Library Exception, version
      // 3.1, as published by the Free Software Foundation.
      
      // You should have received a copy of the GNU General Public License and
      // a copy of the GCC Runtime Library Exception along with this program;
      // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      // <http://www.gnu.org/licenses/>.
      
      /** @file stdc++.h
      *  This is an implementation file for a precompiled header.
      */
      
      // 17.4.1.2 Headers
      
      // C
      #ifndef _GLIBCXX_NO_ASSERT
      #include <cassert>
      #endif
      #include <cctype>
      #include <cerrno>
      #include <cfloat>
      #include <ciso646>
      #include <climits>
      #include <clocale>
      #include <cmath>
      #include <csetjmp>
      #include <csignal>
      #include <cstdarg>
      #include <cstddef>
      #include <cstdio>
      #include <cstdlib>
      #include <cstring>
      #include <ctime>
      
      #if __cplusplus >= 201103L
      #include <ccomplex>
      #include <cfenv>
      #include <cinttypes>
      #include <cstdalign>
      #include <cstdbool>
      #include <cstdint>
      #include <ctgmath>
      #include <cwchar>
      #include <cwctype>
      #endif
      
      // C++
      #include <algorithm>
      #include <bitset>
      #include <complex>
      #include <deque>
      #include <exception>
      #include <fstream>
      #include <functional>
      #include <iomanip>
      #include <ios>
      #include <iosfwd>
      #include <iostream>
      #include <istream>
      #include <iterator>
      #include <limits>
      #include <list>
      #include <locale>
      #include <map>
      #include <memory>
      #include <new>
      #include <numeric>
      #include <ostream>
      #include <queue>
      #include <set>
      #include <sstream>
      #include <stack>
      #include <stdexcept>
      #include <streambuf>
      #include <string>
      #include <typeinfo>
      #include <utility>
      #include <valarray>
      #include <vector>
      
      #if __cplusplus >= 201103L
      #include <array>
      #include <atomic>
      #include <chrono>
      #include <condition_variable>
      #include <forward_list>
      #include <future>
      #include <initializer_list>
      #include <mutex>
      #include <random>
      #include <ratio>
      #include <regex>
      #include <scoped_allocator>
      #include <system_error>
      #include <thread>
      #include <tuple>
      #include <typeindex>
      #include <type_traits>
      #include <unordered_map>
      #include <unordered_set>
      #endif

BOJ 2851번 슈퍼마리오 문제

특별한 알고리즘이 필요한게 아닌 구현 문제이다.

첫번째 버섯부터 무조건 먹는건데 중간에 왜 갑자기 생각을 잘못했는지 중간부터 먹을 수 있게 구현해서 계속 틀려버렸다.

일단 배열에 10개 입력을 받는다.

하나 하나 더해가면서, 100이 넘는 경우에 100에 더하기 전이 가까운지 더한 후가 가까운지 조건을 주고 더 작은 값을 출력한다. 만약 같다면 더한 숫자를 골라야한다.

2851.cpp

#include <iostream>
using namespace std;
int main() {
    int a[10];
    for (int i = 0; i < 10; i++) {
        cin >> a[i];
    }
    int sum = 0;
    for (int i = 0; i < 10; i++) {
        int afterSum = sum + a[i];
        if (afterSum >= 100) {
            if (afterSum - 100 <= 100 - sum) {
                cout << afterSum;
            } else {
                cout << sum;
            }
            return 0;
        }
        sum = afterSum;
    }
    cout << sum;
}

'알고리즘 & SQL > 백준(BOJ)' 카테고리의 다른 글

백준 14753번 : MultiMax C++  (0) 2018.11.02
백준 9086번 : 문자열 C++  (0) 2018.11.02
백준 1427번 : 소트인사이드 C++  (0) 2018.11.02
백준 2998번 : 8진수 C++  (0) 2018.10.31
백준 10987번 : 단위 C++  (0) 2018.10.30

이진트리에서 노드의 수가 가장 많은 레벨 찾기

  • 조건
    1. 루트의 레벨은 1로 한다
    2. 자식의 레벨은 부모의 레벨 + 1이다.
    3. 이진트리에서 같은 레벨에 있는 노드는 같은 행에 위치한다.

노드의 수가 가장 많은 레벨을 출력하는 프로그램을 작성하시오.

  • 입력 형식
    입력 파일의 이름은 input.txt이다. 여러개의 테스트 데이터가 입력될 수 있다. 첫째 줄에는 테스트 데이터의 개수가 입력된다. 둘째 줄에는 첫번째 데이터의 노드의 개수를 나타내는 정수 N(1≤N≤1,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다. 노드들의 번호는 1부터 N까지로 주어진다. 자식이 없는 경우에는 자식노드의 번호가 -1로 주어진다. 루트 노드의 번호는 1이다. 그 다음 줄부터 나머지 데이터가 같은방식으로 주어진다.

  • Test Case

    • 입력
      2
      19
      1 2 3
      2 4 5
      3 6 7
      4 8 -1
      5 9 10
      6 11 12
      7 13 -1
      8 -1 -1
      9 14 15
      10 -1 -1
      11 16 -1
      12 -1 -1
      13 17 -1
      14 -1 -1
      15 18 -1
      16 -1 -1
      17 -1 19
      18 -1 -1
      19 -1 -1
      3
      1 2 3
      2 -1 -1
      3 -1 -1
    • 출력
      4
      2

데이터 노드의 개수가 1과 1000 사이의 정수이기 때문에 전역변수 tree[1001][2]로 잡는다([2]는 왼쪽, 오른쪽 자식).

트리의 노드 별로 레벨을 저장하기 위해 level[1001]을 잡는다. cnt[1001]은 각 레벨의 노드 개수를 저장한다.

테스트 데이터의 개수를 입력 받는다.

여러 번의 테스트를 하므로 tree, level, cnt 배열을 0으로 초기화한다.

노드 1의 레벨을 1로 초기화한다. 노드의 개수를 입력 받는다.

node의 개수만큼 for문을 반복한다.

for문에서는 parent, child1, child2 (부모, 왼쪽 자식, 오른쪽 자식)을 입력 받고 tree에 넣는다.

만약 child1, child2가 -1이 아니면 level[child1], level[child2]를 level[parent]+1 값을 넣는다.

현재 트리의 깊이를 저장하기 위한 max_level을 선언하고 0으로 초기화한다.

node 개수만큼 for문을 반복한다. 노드가 i 레벨일때마다 cnt[i]를 1씩 올린다.

level[i]이 max_level보다 높아지면 max_level에 level[i]를 넣는다.(각 레벨별 노드 개수를 cnt에 저장한다.)

max_level만큼 for문을 반복한다. cnt를 순회하면서 가장 큰 값을 result에 저장한다.

result를 출력하고 다시 반복한다.

이 알고리즘의 시간 복잡도는 한 테스트 케이스당 O(n)이다.(n: 노드의 개수)

#include <fstream>
#include <iostream>
using namespace std;
int tree[1001][2];  // 트리
int level[1001];    // 노드의 레벨
int cnt[1001];      // 각 레벨의 노드 갯수
int main() {
    int n;
    ifstream ifs("input.txt");
    ifs >> n;                              // 테스트 케이스의 개수 입력 받기
    while (n--) {                          // n번 반복
        for (int i = 0; i <= 1001; i++) {  // 0으로 초기화
            tree[i][0] = 0;
            tree[i][1] = 0;
            level[i] = 0;
            cnt[i] = 0;
        }
        level[1] = 1;  // 루트의 레벨은 1
        int node;
        ifs >> node;                      // 노드의 개수 입력 받기
        for (int i = 0; i < node; i++) {  // 노드 개수만큼 반복
            // 부모와 왼쪽, 오른쪽 자식을 입력 받는다.
            int parent, child1, child2;
            ifs >> parent >> child1 >> child2;
            // -1이 아니면 부모의 레벨+1을 자식 레벨에 넣는다.
            if (child1 != -1) {
                tree[parent][0] = child1;
                level[child1] = level[parent] + 1;
            } else {  // -1이면 empty에 1을 추가한다.
                tree[parent][0] = child1;
            }
            // -1이 아니면 부모의 레벨+1을 자식 레벨에 넣는다.
            if (child2 != -1) {
                tree[parent][1] = child2;
                level[child2] = level[parent] + 1;
            } else {  // -1이면 empty에 1을 추가한다.
                tree[parent][1] = child2;
            }
        }
        int max_level = 0;  // 현재 트리가 몇 레벨까지 있는지 저장.
        // 각 레벨별 노드 갯수를 cnt에 저장한다.
        for (int i = 1; i <= node; i++) {
            cnt[level[i]]++;
            if (max_level < level[i]) max_level = level[i];
        }
        int result = 0;
        // 노드가 가장 많은 레벨을 찾는다. 그 때의 레벨을 result에 저장.
        for (int i = 1; i <= max_level; i++) {
            if (result < cnt[i]) {
                result = i;
            }
        }
        // 노드가 가장 많은 레벨을 출력한다.
        cout << result << '\n';
    }
}

코드는 참고만 해주세요.

+ Recent posts