프로그래머스 코딩 테스트 연습문제: 여행경로

728x90

문제 출처: https://programmers.co.kr/learn/courses/30/lessons/43164

 

코딩테스트 연습 - 여행경로 | 프로그래머스

[[ICN, SFO], [ICN, ATL], [SFO, ATL], [ATL, ICN], [ATL,SFO]] [ICN, ATL, ICN, SFO, ATL, SFO]

programmers.co.kr

 

프로그래머스 고득점 Kit 문제 DFS/BFS 문제 Level 3 (마지막 문제)를 푸는데 어려움이 많았다. 
이전까지 풀었던 DFS/BFS와 달리 풀이에 어려움이 많았다. 

문제 설명

주어진 항공권을 모두 이용하여 여행경로를 짜려고 합니다. 항상 ICN 공항에서 출발합니다.

항공권 정보가 담긴 2차원 배열 tickets가 매개변수로 주어질 때, 방문하는 공항 경로를 배열에 담아 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • 모든 공항은 알파벳 대문자 3글자로 이루어집니다.
  • 주어진 공항 수는 3개 이상 10,000개 이하입니다.
  • tickets의 각 행 [a, b]는 a 공항에서 b 공항으로 가는 항공권이 있다는 의미입니다.
  • 주어진 항공권은 모두 사용해야 합니다.
  • 만일 가능한 경로가 2개 이상일 경우 알파벳 순서가 앞서는 경로를 return 합니다.
  • 모든 도시를 방문할 수 없는 경우는 주어지지 않습니다.

입출력 예

tickets                                                                                              return

[[ICN, JFK], [HND, IAD], [JFK, HND]] [ICN, JFK, HND, IAD]
[[ICN, SFO], [ICN, ATL], [SFO, ATL], [ATL, ICN], [ATL,SFO]] [ICN, ATL, ICN, SFO, ATL, SFO]

입출력 예 설명

예제 #1

[ICN, JFK, HND, IAD] 순으로 방문할 수 있습니다.

예제 #2

[ICN, SFO, ATL, ICN, ATL, SFO] 순으로 방문할 수도 있지만 [ICN, ATL, ICN, SFO, ATL, SFO] 가 알파벳 순으로 앞섭니다.

나의 접근 방법은 tickets의 도착지를 알파벳순으로 먼저 정렬한 후에, 출발지가 ICN인 경우에 시작점으로 등록하고, 그 후에 순차적으로 연결되는 항공편을 찾는 방법이었는데, 사용 유무를 표시한 후에 DFS를 실행했을 시에, 해당 경로로 더 이상 진행이 불가능할 경우에 다시 이전 단계로 돌아와야 했는데, (using이라는 boolean 배열을 tickents 행의 길이만큼 선언한 후 시도) 그 해결책을 찾지 못해서 결국 커뮤니티에서 답을 찾았다. 먼저 내가 짠 코드를 먼저 보겠다. (눈이 아플지도 모르니, 주의하자)

● 나의 풀이

public class Solution {

    boolean[] using;
    static ArrayList<String> list;
    static int start;
    static ArrayList<String> banpick;

    public String[] solution(String[][] tickets) {
        String[] answer = {};
        using = new boolean[tickets.length]; //모두 false 로 초기화
        list = new ArrayList<>();
        banpick = new ArrayList<>();
        start = 0;

        Arrays.sort(tickets, new Comparator<String[]>() {
            @Override
            public int compare(String[] o1, String[] o2) {
                return o1[1].compareTo(o2[1]);
            }
        });

        dfs(tickets, start);

        answer = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i);
            System.out.print(answer[i] + " ");
        }

        return answer;
    }

    public void dfs(String[][] tickets, int startPoint) {

        if (list.size() == 0) {
            System.out.println("start:" + start + "-----");
            if (tickets[startPoint][0].equals("ICN")) {
                list.add(tickets[startPoint][0]); // "ICN"이다.
                System.out.println(tickets[startPoint][0] + "추가 size:" + list.size());
                list.add(tickets[startPoint][1]);
                System.out.println(tickets[startPoint][1] + "추가 size:" + list.size());
                using[startPoint] = true;
            } else {
                dfs(tickets, ++start);
                return;
            }
        }

        int cnt = 0;
        boolean[] check = new boolean[tickets.length];//false로 초기화
        //이전 내용 저장

        for (int i = 0; i < tickets.length; i++) {
            if (!using[i] && tickets[startPoint][1].equals(tickets[i][0])) {
                if (!banpick.contains(tickets[i][0])) {
                    cnt++;
                    check[i] = true;
                }
            }
        }

        boolean[] befusing = using;
        ArrayList<String> beflist = list;
        // 다음으로 넘어가는 티켓이 없는경우 이전단계로 회기한다.
        if (cnt == 0 && list.size() != tickets.length + 1) {
            //이전단계로 돌아가고 문제가 발생한 부분 뛰어넘게 만들기....
            banpick.add(tickets[startPoint][1]);
            System.out.println("도착지 = 출발지 일치x clear 했음");
            list.clear(); //좋은 방법이 아닌것같다.
            list = beflist;
            using = new boolean[tickets.length];

            dfs(tickets, start);

            banpick.clear();
        }

        if (list.size() == tickets.length + 1) {
            System.out.println("size:" + list.size());
            return;
        }

        for (int i = 0; i < check.length; i++) {
            if (check[i]) {
                list.add(tickets[i][1]);
                System.out.println(tickets[i][1] + " 추가 size:" + list.size());
                using[i] = true;
                dfs(tickets, i);
            }
        }

    }
}

 

이 풀이는 4개의 테스트 케이스 중에 4번 테스트 케이스를 통과하지 못해서 테스트를 통과하지 못했다.
(실제로임의로 만들어본 예제 String [][]= {{"ICN", "COO"}, {"COO", "ICN"}, {"COO", "ICN"}, {"ICN", "COO"}, {"ICN", "AAA"}};  예제도 통과하지 못했다) 

풀이 참고: https://youjourney.tistory.com/111

 

[프로그래머스] 여행경로 (java)(43164)

원본 문제 : https://programmers.co.kr/learn/courses/30/lessons/43164 문제 참고 : https://geehye.github.io/programmers-dfs-bfs-04/# 문제 설명 주어진 항공권을 모두 이용하여 여행경로를 짜려고 합니다...

youjourney.tistory.com

 

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Solution {
    
    static boolean visit[];
	static List<String> list = new ArrayList<>();
	static String route = "";
    
    public String[] solution(String[][] tickets) {
        visit = new boolean[tickets.length];
		
		for(int i = 0 ; i < tickets.length; i++) {
			
			String departure = tickets[i][0];
			String destination = tickets[i][1];
			
			if(departure.equals("ICN")) {
				visit[i] = true;
				route = departure + ",";
				dfs(tickets, destination, 1);
				visit[i] = false;
			}
		}
		
		Collections.sort(list);
		String[] answer = list.get(0).split(",");
		return answer;
    }
	
	public static void dfs(String[][] tickets, String end, int count) {
		
		route += end + ",";
		
		if(count==tickets.length) {
			list.add(route);
			return;
		}
		
		for(int i = 0 ; i < tickets.length ; i++) {
			String depart = tickets[i][0];
			String desti = tickets[i][1];
			
			if(end.equals(depart) && !visit[i]) {
				visit[i] = true;
				dfs(tickets, desti, count+1);
				visit[i] = false;
				route = route.substring(0, route.length()-4);
			}
		}
	}
}

 

728x90