park345601   5년 전

코드를 짜고 올라온 반례들을 질문게시판을 뒤져가며 어느정도 다 고친것 같은데

ArrayList[] a = (ArrayList[]) new ArrayList[n];

코드 중에 이부분에서 

type safety :unchecked cast from ArrayList[] to ArrayList<Integer>[]

라고 뜨면서 SuppressWarnings 어노테이션을 붙이라고 뜨는데

이것때문에 코드가 틀렸다고 나올수도 있는건가요?

그리고 형식에 맞는게 아니면 어떻게 써야될까요..?


arraylist를 element로 갖는 배열을 만들고 싶었는데 잘 모르겠어서 도움부탁드립니다!

djm03178   5년 전

그 부분은 관계 없다고 보입니다.

문제는 dfs를 하는 부분에 있는데, 중복 방문을 제거하기 위해 많은 노력을 하신 것 같지만 사실은 여전히 중복 방문이 일어날 수 있습니다.

아래와 같은 케이스에서 dfs는 1 2 3 4 5 6 을 출력해야 합니다.

dfs 문제에서 일반적으로는 간선을 제거하려고 할 필요가 없습니다. 정점에 방문 체크를 해주고, 이미 방문한 정점이면 단순히 스택이 넣지 않으면 되기 때문입니다. 지금처럼 일반적인 리스트에서 간선을 하나씩 지워내는 것은 시간복잡도상으로도 좋지 못합니다.

팁으로, dfs는 직접 스택을 이용하는 것보다 재귀 함수로 구현하는 것이 편합니다.

djm03178   5년 전

사실 지금의 dfs 코드를 보면, 어떤 정점을 방문한 뒤에 오직 하나의 인접한 정점만을 스택에 삽입하고 그 간선을 제거해버리고 있는데, 재귀를 이용하면 그 과정을 매우 편하게 할 수 있지만 지금처럼 반복문으로 해결하려고 할 때는 그보다는 먼저 현재 정점을 pop 해버린 다음, 이미 현재 정점을 방문한 적이 있다면 스킵하고, 아니라면 방문 여부를 표시하고 현재 정점에 연결된 간선을 역순으로 스택에 모두 한 번에 삽입해버리는 것이 낫습니다.

park345601   5년 전

감사합니다 덕분에 dfs코드를 방문여부체크를 통해서 해결하도록 바꿔서 문제는 맞췄습니다!

재귀함수로도 짜봐야겠네요!!


그리고 bfs도 방문여부로 체크하는게 시간복잡도를 줄일수있나요?

djm03178   5년 전

기본적으로 배열에서 원소 하나를 제거하는 건 O(배열에 들어있는 원소 수)만큼의 시간이 걸립니다. 해당 원소가 있는지 순회해서 찾아야 할 뿐만 아니라, 그 뒤에 있는 원소들을 전부 한 칸씩 앞으로 당겨와야 하기 때문입니다. 그래서 E개의 간선 모두를 제거하는 데에 최악의 경우 O(E^2)의 시간이 소요될 수 있습니다.

하지만 단순히 정점에 방문 체크를 해준다면 이러한 과정이 없이 E개의 간선을 도는 동안 V개의 정점에 체크만 해주면 되므로 O(E+V)로 시간복잡도를 크게 개선할 수 있습니다.

park345601   5년 전

재귀를 안썼는데도 

dfs bfs 둘다 방문여부 확인으로 해줬더니 시간이 많이 줄어드네요

도움주셔서 감사합니다!!

댓글을 작성하려면 로그인해야 합니다.