hyelie
hyelie
Hyeil Jeong
       
글쓰기    관리    수식입력
  • 전체보기 (495)
    • PS (283)
      • Algorithm (28)
      • PS Log (244)
      • Contest (6)
      • Tips (5)
    • Development (52)
      • Java (14)
      • Spring (23)
      • SQL (2)
      • Node.js (2)
      • Socket.io (3)
      • Study (4)
      • Utils (4)
    • DevOps (36)
      • Git (5)
      • Docker (4)
      • Kubernetes (2)
      • GCP (3)
      • Environment Set Up (8)
      • Tutorial (12)
      • Figma (2)
    • CS (74)
      • OOP (7)
      • OS (24)
      • DB (2)
      • Network (24)
      • Architecture (0)
      • Security (2)
      • Software Design (0)
      • Parallel Computing (15)
    • Project (15)
      • Project N2T (5)
      • Project ASG (0)
      • Project Meerkat (1)
      • Model Checking (7)
      • Ideas (2)
    • 내가 하고싶은 것! (34)
      • Plan (16)
      • Software Maestro (10)
      • 취준 (8)
hELLO · Designed By 정상우.
hyelie

hyelie

PS/PS Log

23.04.09. 풀었던 문제들

Leetcode 1857. Largest Color Value in a Directed Graph

 문제를 읽고, 일단 귀찮은 문제라는 것은 깨달았다. 해야 하는 것만 해도

  • cycle 존재 여부 검증
  • cycle이 없는 경우, 모든 path에 대해 모든 색깔의 경우의 수를 구해야 한다.

 이 문제의 경우 outgoing edge가 1개라는 조건이 없기 때문에 일반적인 directed graph에서 cycle 여부를 검증하는 방법을 사용해야 했고, 모든 path를 탐색해야 한다는 점에서 topological sort가 떠올랐다. 그러나 topological sort를 사용한 지 오래되어서 해당 구현은 이전에 쓴 게시글을 참고했다. 

 

 topological sort의 큰 로직은 아래와 같다.

  • source vertex를 찾고 모든 source를 queue에 넣는다. ... 1
  • q의 front()와 해당 vertex에 연결된 adjacent vertex로의 edge를 graph에서 삭제한다.  ... 2
    • 이 때 graph에서 직접 삭제하지 말고, incoming edge 개수를 따로 저장해둔 후 이 단계에서 q.front()와 q.front()의 adj를 잇는 edge의 incoming edge 개수를 1 줄인다.
    • 만약 adj의 incoming edge 개수가 0이라면 q에 push한다.
  • 모든 graph의 edge에 대해 탐색한다.
  • 만약 탐색이 끝나기 전 queue size가 0이라면 source vertex가 없는 것이므로, 즉 cycle이 있는 것을 의미한다. 만약 queue size가 1보다 크다면 topological sort 결과가 2개 이상이라는 것이다.
  • 이 경우 시간복잡도는 O(V + E)이다.

 

 이 문제의 경우 connected directed graph이므로 queue size가 0이 되는지 여부만 탐색하면 cycle 여부를 알 수 있다.

 이렇게 cycle 여부를 알아낸 뒤에는 모든 path에 대해 모든 색깔의 경우의 수를 탐색해 주어야 한다. 우리는 이미 topological sort를 통해 path의 진행방향으로만 vertex를 탐색한다. 따라서 배열 하나를 추가한다.

  • num_color[v][c]는 vertex v까지 탐색했을 때, color c의 개수이다.
  • q.pop()을 했다는 것은 source vertex 하나가 줄어드는 것이며, 해당 vertex까지 path를 탐색했다는 것이다. 이 때 해당 vertex의 color는 반영되지 않았으므로 num_color[front][color[front]-'a']++을 해 주고, 정답을 같이 갱신해 준다. ... 3-1.
  • 또한 q.front()의 adjacent vertex를 탐색할 때, q.front()의 num_color를 이용해 q.front().adjacent의 num_color도 갱신해 준다. ... 3-2.
class Solution {
public:
    int n;
    vector<vector<int>> edges;
    vector<int> num_income;
    int largestPathValue(string colors, vector<vector<int>>& e) {
        // initialize
        n = colors.size();
        edges.resize(n);
        num_income.resize(n); // ... 1. source를 찾기 위함.
        for(vector<int> vi : e){
            edges[vi[0]].push_back(vi[1]);
            num_income[vi[1]]++;
        }

        // ... 1.
        queue<int> q;
        for(int i = 0; i<n; i++){
            if(num_income[i] == 0){
                q.push(i);
            }
        }

        bool hasCycle = false;
        vector<vector<int>> num_color(n, vector<int>(26, 0)); // num_color[v][c] : vertex v까지 탐색했을 때 color c가 나온 회수
        int answer = -1;
        for(int i = 0; i<n; i++){
            if(q.empty()){
                return -1;
            }

            int front = q.front(); q.pop();
            num_color[front][colors[front] - 'a']++;
            answer = max(answer, num_color[front][colors[front] - 'a']); /// ... 3-1.
            
            // ... 2.
            for(int adj : edges[front]){
                num_income[adj]--;
                if(num_income[adj] == 0) q.push(adj);

                // ... 3-2.
                for(int i = 0; i<26; i++){
                    num_color[adj][i] = max(num_color[front][i], num_color[adj][i]);
                }
            }
        }

        return answer;
    }
};

 

시간복잡도

 topological sort에 O(V + E), V = n, E = m이므로 O(n+m)이다. 그리고 각 탐색에서 size 26만큼의 for문을 돌리지만 이는 시간복잡도에 영향을 주지는 않는다. 따라서 O(n+m).

 

공간복잡도

 q에 worst case O(V)만큼 들어가고 edge에 O(E), num_income에 O(V), num_color에 O(V)만큼 들어가므로 O(n+m)이다.

 

후기

 topological sort에 dp를 적용하는 문제였다. 빡셌다.

 

 

 

 

저작자표시 (새창열림)

'PS > PS Log' 카테고리의 다른 글

23.04.11. 풀었던 문제들  (0) 2023.04.11
23.04.10. 풀었던 문제들  (0) 2023.04.10
23.04.08. 풀었던 문제들  (0) 2023.04.08
23.04.07. 풀었던 문제들  (0) 2023.04.07
23.04.06. 풀었던 문제들  (0) 2023.04.06
    hyelie
    hyelie

    티스토리툴바