-
[프로그래머스/JAVA] 여행경로Algorithm 2024. 10. 14. 20:20
https://school.programmers.co.kr/learn/courses/30/lessons/43164
- 문제 풀이
1.변수 선언 및 초기화
- list: 모든 가능한 경로를 저장하는 리스트입니다. 탐색을 마친 경로는 여기에 저장됩니다.
- visited: 각 항공권이 사용되었는지 여부를 기록하는 배열입니다. 이미 사용한 티켓을 다시 사용하지 않도록 하기 위한 배열입니다.
import java.util.*; class Solution { // 방문한 경로들을 저장할 리스트 static ArrayList<String> list = new ArrayList<>(); // 항공권 사용 여부 기록하는 배열 static boolean visited[]; .... public String[] solution(String[][] tickets) { visited = new boolean[tickets.length];
2.DFS 탐색 함수 (dfs) 정의
이 함수는 현재 공항에서 출발하여, 가능한 다음 목적지로 이동하며 경로를 찾는 재귀적인 탐색입니다.
- depth: 현재까지 사용한 티켓의 수를 나타냅니다. 모든 티켓을 다 사용하면 탐색을 종료합니다.
- now: 현재 위치하고 있는 공항입니다. 출발할 공항을 의미합니다.
- path: 현재까지 거쳐온 경로를 저장하는 문자열입니다. 경로는 공백을 기준으로 구분합니다.
- tickets: 항공권 정보를 담고 있는 2차원 배열입니다. 각 티켓은 [출발지, 도착지]로 되어 있습니다.
static void dfs(int depth, String now, String path, String[][] tickets) {
public String[] solution(String[][] tickets) { visited = new boolean[tickets.length]; // DFS 탐색 시작: 초기 상태는 "ICN" 공항에서 출발하고, 경로도 "ICN"으로 시작 dfs(0, "ICN", "ICN", tickets);
3. DFS 로직 설명
- 기저 조건: depth가 tickets.length와 같으면, 즉, 모든 티켓을 다 사용한 경우에는 탐색을 종료합니다. 이때까지 지나온 경로(path)를 list에 추가합니다.
- 현재 공항에서 출발하는 티켓 탐색:
- 모든 티켓을 순회하면서, 아직 사용하지 않은 티켓 중 출발 공항이 현재 공항과 일치하는 티켓을 찾습니다.
- 해당 티켓이 조건에 맞다면 visited[i] = true로 설정해 사용한 티켓임을 표시하고, 그 티켓의 목적지로 이동하여 다시 DFS를 호출합니다.
- 목적지로 이동할 때, 경로도 업데이트해 path + " " + tickets[i][1]처럼 목적지를 이어 붙여 나갑니다.
- 백트래킹: 모든 경로를 탐색하기 위해 DFS 재귀 호출이 끝나면, 다시 그 티켓을 사용하지 않은 상태로 돌려놓습니다 (visited[i] = false). 이렇게 해야 다른 경로에서도 해당 티켓을 사용할 수 있게 됩니다.
static void dfs(int depth, String now, String path, String[][] tickets) { // 모든 티켓을 다 사용하면 if (depth == tickets.length) { // 해당 경로(path)를 리스트에 추가하고 종료 list.add(path); return; } // 현재 공항(now)에서 출발하는 모든 티켓을 탐색 for (int i = 0; i < visited.length; i++) { // 티켓이 아직 사용되지 않았고, 출발 공항이 현재 공항과 일치하는지 확인 if(!visited[i] && now.equals(tickets[i][0])) { visited[i] = true; // 재귀 호출: 목적지로 이동하고, 경로 업데이트 dfs(depth + 1, tickets[i][1], path + " " + tickets[i][1], tickets); // 해당 티켓을 자시 사용 가능한 상태로 되돌림(백트래킹) visited[i] = false; } } }
4. 메인 함수 (solution) 설명
- visited 배열은 항공권의 수만큼 크기를 설정하고, 아직 아무 티켓도 사용하지 않았으므로 초기값은 모두 false입니다.
- DFS 탐색을 시작하는데, 출발 공항은 항상 "ICN"이므로 처음 호출은 dfs(0, "ICN", "ICN", tickets)로 시작합니다. 경로의 시작도 "ICN"입니다.
- 모든 가능한 경로가 list에 저장되면, 이를 알파벳 순서로 정렬합니다. 문제에서 요구한 조건대로 가장 알파벳 순서상 앞서는 경로가 최종 경로가 됩니다.
- 경로는 공백으로 구분되어 있으므로, 이를 split(" ")하여 문자열 배열로 반환합니다.
public String[] solution(String[][] tickets) { visited = new boolean[tickets.length]; // DFS 탐색 시작: 초기 상태는 "ICN" 공항에서 출발하고, 경로도 "ICN"으로 시작 dfs(0, "ICN", "ICN", tickets); // list에 저장된 경로들 알파벳 순으로 정렬 Collections.sort(list); // 가장 알파벳 순서 앞서는 경로 선택해서 공백 기준으로 나눈 후 리턴 return list.get(0).split(" "); }
+ Collections.sort() 정렬 부분 ?
알파벳 순서로 정렬하는 것은 ICN에서 출발한 후 나머지 공항들에 대한 순서를 의미합니다. 즉, 경로 중간에 등장하는 공항들이 알파벳 순서로 가장 앞서는 경로를 찾는 것입니다.
예시로 설명:
티켓을 사용하여 다음과 같은 경로들이 완성되었다고 가정해 봅시다:
- "ICN SFO ATL ICN ATL SFO"
- "ICN ATL SFO ICN SFO ATL"
이 경로들을 Collections.sort(list)로 정렬하면, 경로는 다음과 같이 정렬됩니다:
- "ICN ATL SFO ICN SFO ATL"
- "ICN SFO ATL ICN ATL SFO"
즉, "ICN"에서 출발하는 것은 고정이고, "ICN" 이후의 경로들이 알파벳 순서로 정렬됩니다.
- 정답 코드
import java.util.*; class Solution { // 방문한 경로들을 저장할 리스트 static ArrayList<String> list = new ArrayList<>(); // 항공권 사용 여부 기록하는 배열 static boolean visited[]; static void dfs(int depth, String now, String path, String[][] tickets) { // 모든 티켓을 다 사용하면 if (depth == tickets.length) { // 해당 경로(path)를 리스트에 추가하고 종료 list.add(path); return; } // 현재 공항(now)에서 출발하는 모든 티켓을 탐색 for (int i = 0; i < visited.length; i++) { // 티켓이 아직 사용되지 않았고, 출발 공항이 현재 공항과 일치하는지 확인 if(!visited[i] && now.equals(tickets[i][0])) { visited[i] = true; // 재귀 호출: 목적지로 이동하고, 경로 업데이트 dfs(depth + 1, tickets[i][1], path + " " + tickets[i][1], tickets); // 해당 티켓을 자시 사용 가능한 상태로 되돌림(백트래킹) visited[i] = false; } } } public String[] solution(String[][] tickets) { visited = new boolean[tickets.length]; // DFS 탐색 시작: 초기 상태는 "ICN" 공항에서 출발하고, 경로도 "ICN"으로 시작 dfs(0, "ICN", "ICN", tickets); // list에 저장된 경로들 알파벳 순으로 정렬 Collections.sort(list); // 가장 알파벳 순서 앞서는 경로 선택해서 공백 기준으로 나눈 후 리턴 return list.get(0).split(" "); } }
'Algorithm' 카테고리의 다른 글
[프로그래머스/JAVA] 구명보트 (0) 2024.10.16 [프로그래머스/JAVA] 체육복 (0) 2024.10.15 [프로그래머스/JAVA] 단어 변환 (0) 2024.10.06 [프로그래머스/JAVA] 네트워크 (0) 2024.10.05 [프로그래머스/JAVA] 타겟 넘버 (0) 2024.09.18