Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 이진 트리의 왼쪽 뷰(Left View) 구하기

이진 트리가 하나 주어졌다고 가정해 봅시다. 이 트리를 왼쪽에서 바라보면 특정 노드들만 보이게 되는데, 우리는 그 보이는 노드들을 출력해야 합니다.

예를 들어 트리가 다음과 같다면 −

C++로 이진 트리의 왼쪽 뷰(Left View) 구하기

출력 결과는 [1, 2, 5]가 됩니다. 왼쪽에서 볼 때 루트 노드 1, 두 번째 깊이에서 가장 왼쪽에 있는 노드 2, 세 번째 깊이에서 가장 왼쪽에 있는 노드 5만 보이기 때문입니다.

접근 방법

이 문제는 DFS(깊이 우선 탐색)와 깊이(depth) 추적을 활용하면 효율적으로 해결할 수 있습니다. 핵심 아이디어는 각 깊이에서 가장 먼저 방문되는 노드가 곧 왼쪽 뷰에 해당한다는 점입니다. 왼쪽 자식을 오른쪽 자식보다 먼저 탐색하기 때문입니다.

해결 절차는 다음과 같습니다 −

  • 결과를 저장할 배열 ret을 정의합니다.
  • 매개변수로 노드(node)와 현재 깊이(c, 기본값 1)를 받는 dfs() 함수를 정의합니다.
  • node가 null이면 함수를 종료(return)합니다.
  • c > lvl이라면, 즉 현재 깊이가 지금까지 방문한 최대 깊이보다 크다면 −
    • lvl := c로 최대 깊이를 갱신합니다.
    • 현재 노드의 값을 ret에 삽입합니다.
  • dfs(node의 왼쪽 자식, c + 1)을 재귀 호출합니다.
  • dfs(node의 오른쪽 자식, c + 1)을 재귀 호출합니다.
  • 메인 함수에서는 다음을 수행합니다 −
    • lvl := -1로 초기화합니다.
    • dfs(root, 0)을 호출합니다.
    • ret을 반환합니다.

시간 복잡도는 모든 노드를 한 번씩 방문하므로 O(N)이며, 공간 복잡도는 재귀 호출 스택으로 인해 최악의 경우 O(N)입니다.

구현 예제

다음 코드를 통해 더 자세히 이해해 보겠습니다 −

#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<int> v){
    cout << "[";
    for(int i = 0; i<v.size(); i++){
        cout << v[i] << ", ";
    }
    cout << "]"<<endl;
}
class TreeNode{
    public:
    int val;
    TreeNode *left, *right;
    TreeNode(int data){
        val = data;
        left = right = NULL;
    }
};
class Solution {
    public:
    vector <int> ret;
    int lvl;
    void dfs(TreeNode* node, int c = 1){
        if(!node)
            return;
        if(c > lvl){
            lvl = c;
            ret.push_back(node->val);
        }
        dfs(node->left, c + 1);
        dfs(node->right, c + 1);
    }
    vector<int> solve(TreeNode* root) {
        lvl = -1;
        dfs(root, 0);
        return ret;
    }
};
main(){
    TreeNode *root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->right = new TreeNode(5);
    root->right->right = new TreeNode(4);
    Solution ob;
    print_vector(ob.solve(root));
}

입력

TreeNode *root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->right = new TreeNode(5);
root->right->right = new TreeNode(4);

출력

[1,2,5]

위 코드에서 dfs() 함수는 왼쪽 자식을 먼저 방문하므로, 각 깊이에 도달하는 첫 번째 노드가 항상 해당 깊이에서 가장 왼쪽에 있는 노드가 됩니다. 조건 c > lvl은 같은 깊이의 노드가 여러 번 기록되지 않도록 중복을 방지하는 역할을 합니다.