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.08. 풀었던 문제들

Leetcode 133. Clone Graph

 Node pointer로 이루어진 graph 하나를 clone하는 문제. 중복된 edge는 없고, 각 Node가 가지고 있는 val은 unique하다는 조건에서 시작한다.

 사실상 그렇게 어려운 문제는 아니다. DFS나 BFS를 쓰고, 그 과정에서 몇 줄만 추가해 주면 되는 문제.

 

첫 접근

 일단 BFS로 풀었다. naive하게 2번의 BFS를 했다.

  • 첫 BFS에서는 unvisit인 모든 Node에 대해 clone을 생성한다. 생성한 Node clone들을 value를 key로 가지는 map에 저장한다. ... 1
  • 두 번째 BFS에서는 edge를 연결한다. 첫 번째 BFS에서 모든 Node를 찾았기 때문에 두 번째 BFS에서는 모든 clone들의 edge만 연결해 주면 된다.
// Runtime 9 ms Beats 23.26%
// Memory 8.8 MB Beats 65.38%

class Solution {
public:
    Node* copyroot;
    Node* cloneGraph(Node* node) {
        if(node == NULL) return NULL;

        queue<Node*> q;
        set<Node*> visited;
        map<int, Node*> m; // mapper of clone node 

        // ...1
        q.push(node);
        visited.insert(node);
        while(!q.empty()){
            Node* origin = q.front(); q.pop();
            visited.insert(origin);

            if(m.find(origin->val) == m.end()){
                m[origin->val] = new Node(origin->val);
            }

            for(Node* adj : origin->neighbors){
                if(visited.find(adj) == visited.end()){
                    q.push(adj);
                }
            }                        
        }
 
        // ... 2
        q.push(node);
        visited.clear();
        visited.insert(node);
        while(!q.empty()){
            Node* origin = q.front(); q.pop();
            visited.insert(origin);

            for(Node* adj : origin->neighbors){
                if(visited.find(adj) == visited.end()){
                    m[origin->val]->neighbors.push_back(m[adj->val]);
                    m[adj->val]->neighbors.push_back(m[origin->val]);
                    q.push(adj);
                }
            }                        
        }

        return m[1];
    }
};

 

 

두 번째 접근

 BFS 1번으로 해결할 수 없을까? 가능할 거라 생각했다. BFS에서 unvisit한 Node를 방문할 때 새 Node를 생성하고 map에 넣는다. 그렇지 않다면 이미 map에 들어가 있는 상태일 것이다.

 따라서 어떤 Node의 neighbor를 탐색할 때 edge를 바로 연결해 줄 수 있다.

// Runtime 7 ms Beats 61.34%
// Memory 8.8 MB Beats 53.37%

class Solution {
public:
    Node* copyroot;
    Node* cloneGraph(Node* node) {
        if(node == NULL) return NULL;

        queue<Node*> q;
        set<Node*> visited;
        map<int, Node*> m; // mapper of clone node 

        q.push(node);
        visited.insert(node);
        while(!q.empty()){
            Node* origin = q.front(); q.pop();
            visited.insert(origin);

            if(m.find(origin->val) == m.end()){
                m[origin->val] = new Node(origin->val);
            }

            for(Node* adj : origin->neighbors){
                if(m.find(adj->val) == m.end()){
                    m[adj->val] = new Node(adj->val);
                    q.push(adj);
                }
                m[origin->val]->neighbors.push_back(m[adj->val]);
            }                        
        }

        return m[1];
    }
};

 

 

세 번째 접근

 조금 더 최적화했다. BFS의 모든 단계에서 [현 Node가 unvisit이면 새로운 Node를 생성]하고, 또 [현 Node의 모든 neighbor를 탐색할 때 unvisit이면 새로운 Node를 생성]하는 로직이 겹치기 때문에 이를 수정했다. 또 사용하지 않는 visited set을 버렸다.

// Runtime 7 ms Beats 61.34%
// Memory 8.7 MB Beats 65.38%

class Solution {
public:
    Node* copyroot;
    Node* cloneGraph(Node* node) {
        if(node == NULL) return NULL;

        queue<Node*> q;
        map<int, Node*> m; // mapper of clone node 

        if(m.find(node->val) == m.end()){
            m[node->val] = new Node(node->val);
        }

        q.push(node);
        while(!q.empty()){
            Node* origin = q.front(); q.pop();

            for(Node* adj : origin->neighbors){
                if(m.find(adj->val) == m.end()){
                    m[adj->val] = new Node(adj->val);
                    q.push(adj);
                }
                m[origin->val]->neighbors.push_back(m[adj->val]);
            }                        
        }

        return m[1];
    }
};

 

 

시간복잡도

 각 접근마다 BFS를 2번, 또는 1번 하므로 O(V+E).

 

공간복잡도

 worst case q, visited, set에 각각 O(V)만큼 들어간다. 따라서 O(V)

 

 

 

 

 

 

저작자표시 (새창열림)

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

23.04.10. 풀었던 문제들  (0) 2023.04.10
23.04.09. 풀었던 문제들  (0) 2023.04.09
23.04.07. 풀었던 문제들  (0) 2023.04.07
23.04.06. 풀었던 문제들  (0) 2023.04.06
23.04.05. 풀었던 문제들  (0) 2023.04.05
    hyelie
    hyelie

    티스토리툴바