Google 태그 관리자 아이콘

알고리즘 풀이

.leetcode(547. Number of Provinces)

silvergoni 2022. 4. 11. 10:09
반응형

https://leetcode.com/problems/number-of-provinces/

 

1. 2022/04/10 시도

소요시간: 38분

class Solution {
    private int[] rootArray;
    private int[] rank;
    public int findCircleNum(int[][] isConnected) {
        rootArray = new int[isConnected.length];
        rank = new int[isConnected.length];
        
        //init
        for (int i=0; i<rootArray.length; i++) {
            rootArray[i] = i;
            rank[i] = 1;
        }

        for (int i=0; i<rootArray.length; i++) {
            for (int j=i+1; j<rootArray.length; j++) {
                if (isConnected[i][j] == 1) {
                    union(i, j);
                }
            }
        }
        
        Set<Integer> provinces = new HashSet<>();
        for (int i=0; i<rootArray.length; i++) {
            provinces.add(find(i));
        }
        
        return provinces.size();
    }
    
    private int find(int index) {
        if (index == rootArray[index]) {
            return index;
        }
        
        return rootArray[index] = find(rootArray[index]);
    }
    
    private void union(int i, int j) {
        int rootX = find(i);
        int rootY = find(j);
        if (rank[rootX] > rank[rootY]) {
            rootArray[rootY] = rootX;
        } else if (rank[rootX] < rank[rootY]) {
            rootArray[rootX] = rootY;
        } else {
            rootArray[rootX] = rootY;
            rank[rootY] += 1;
        }
    }
}

풀이 접근 과정

그래프 풀이로 접근했다.

find, union을 정의하고 세팅을 초기화해준다.

isConnected가 허용될 때만 union을 시킨다.

마지막 set을 통해 unique한 root를 세면 된다.

기본적으로 for 루프가 2번 돌고 union메소드에서 find메소드를 사용하는데, 이 때 또 O(n)이 되어 최종 O(n^3)의 시간복잡도를 갖는다.

 

느낀점

  • 그래프에 대해서 공부하면서 이번 풀이를 풀었는데 시간복잡도가 길지만 굉장히 재미있는 접근이다. 예전에 위키에 대한 설계를 하면서 이런 접근을 했었는데 그때는 parent개념만 두었는데 그래프처럼 root개념을 적용했다면 좀 더 효율적인 설계가 되었을지 궁금해졌다.
  • dfs로도 풀 수 있다. visited와 dfs조합으로 하면 O(n^2)의 시간복잡도로도 풀 수 있다.
//dfs
class Solution {
    public int findCircleNum(int[][] isConnected) {
        boolean[] visited = new boolean[isConnected.length];
        
        int counter = 0;
        for (int i=0; i< visited.length; i++) {
            if (visited[i] == false) {
                dfs(isConnected, visited, i);
                counter ++;
            }
        }
        
        return counter;
    }
    
    private void dfs(int[][] isConnected, boolean[] visited, int from) {
        for (int i=0; i<visited.length; i++) {
            if (isConnected[from][i] == 1 && visited[i] == false) {
                visited[i] = true; 
                dfs(isConnected, visited, i);
            }
        }
    }
}
  • 솔루션을 참고하면, bfs로도 풀 수 있다. 내가 보기엔 isConnected가 2차원배열이기때문에 가능한 것으로 보인다. N차원이었으면 bfs로는 불가능하지 않았을까 한다.
class Solution {
    
    public int findCircleNum(int[][] isConnected) {
        boolean[] V = new boolean[isConnected.length];
        
        Queue<Integer> queue = new LinkedList<>();
        
        int counter = 0;
        for (int i=0; i<V.length; i++) {
            if (V[i] == false) {
                queue.offer(i);
                while(!queue.isEmpty()) {
                    int from = queue.remove();
                    for (int j=0; j<V.length; j++) {
                        if (isConnected[from][j] == 1 && V[j] == false) {
                            queue.offer(j);
                            V[j] = true;
                        }
                    }
                }
                counter++;
            }
        }
        
        return counter;
    }
}

알고리즘 정리노트: .leetcode(알고리즘 문제풀이 접근)

반응형

 

'알고리즘 풀이' 카테고리의 다른 글

.leetcode(1971. Find if Path Exists in Graph)  (0) 2022.04.14
.leetcode(261. Graph Valid Tree)  (0) 2022.04.12
.review(알고리즘 문제풀이 접근)  (0) 2022.04.11
.programmers(조이스틱)  (0) 2022.04.09
.programmers(체육복)  (0) 2022.04.09