Test - Programmers2

 

1. Lv.2

  • 33문제 풀기 :
    • 정답률 높은 순서
    • 약 3만명 이상 푼 문제부터 풀고 Kakao 문제는 거의 다 풀기
    • 문제 당, 최대 2시간 고민


1) 최댓값과 최솟값

  • compareTo는 문자열 정렬 시, 사용! **

import java.util.*;

class Solution {
    public String solution(String s) {
        String[] sp = s.split(" ");
        String answer = "";
        int[] num = new int[sp.length];
        
        for(int i = 0; i < sp.length; i++){
            num[i] = Integer.parseInt(sp[i]);
        }
        
        Arrays.sort(num);
        
        for(int i = 0; i < num.length; i++){
            answer = num[0] + " " + num[sp.length-1];
        }
       
        // ** compareTo는 문자열 정렬시, 사용! ** 
        // Arrays.sort(sp, (o1,o2) -> (o1).compareTo(o2));
    
        // for(int i = 0; i < sp.length; i++){
        //     answer = sp[0] + " " + sp[sp.length-1];
        // }
       
        return answer;
    }
}




2) JadenCase 문자열 만들기

  • 테케 8번만 실패, 연속된 공백 어떻게 없앨까?
    • 다시 풀기!
import java.util.*;

class Solution {
    public String solution(String s) {
        String[] sp = s.split(" ");
        String answer = "";
        List<String> ls = new ArrayList<>();
        
        for(int i = 0; i < sp.length; i++){
            ls.add(sp[i]);
        }
        
        for(int i = 0; i < sp.length; i++){
            if(ls.get(i).equals(" "))
                ls.remove(i--);
                
            String[] s1 = ls.get(i).split("");
            
            s1[0] = s1[0].toUpperCase();
            
             for(int j = 0; j < s1.length; j++){
                if(j != 0)
                    s1[j] = s1[j].toLowerCase();
            
                answer += s1[j];
             }
            
            if(i != sp.length - 1)
                answer += " ";
        }
        return answer;
    }
}



3) 올바른 괄호

  • 첫 번째 코드 :
    • 테스트 전부 통과하지만, 시간 초과
    • 수정하기
class Solution {
    boolean solution(String s) {
        
        String[] sp = s.split("");
        boolean count1 = true;
        
        boolean answer = true;
        
        for(int i = 0; i < sp.length; i++){
            if(sp[i].equals("("))
                count1 = true;
            
            else if(sp[i].equals(")"))
                count1 = false;
        }
        
        if(count1 == false)
            answer = true;
        else
            answer = false;
        

        return answer;
    }
}

  • 두 번째 코드 :
    • 반환 타입이 boolean이라서 false로 반환하기!
    • return 0보다는 return false를 더 많이 사용할 것!
import java.util.*;

class Solution {
    boolean solution(String s) {
        
        // String[] sp = s.split("");
        boolean check = true;
        boolean answer = true;
        int cnt = 0;
        
        for(int i = 0; i < s.length(); i++){
            if(s.charAt(i) == '('){
                check = true;
                cnt++;
            }

            else if(s.charAt(i) == ')'){
                check = false;
                cnt--;
            }
            
            // 반환 타입이 boolean이라서 false로 반환하기!
            if(cnt < 0)
                return false;
            
        }
        
        if(cnt != 0)
            answer = false;
        else
            answer = true;
        

        return answer;
    }
}



4) 최솟값 만들기

  • 첫번째 풀이 : 수정하기. 절반만 맞았다.

import java.util.*;


class Solution
{
    public int solution(int[] A, int[] B)
    {
        int answer = 0;
        List<Integer> list1 = new ArrayList<Integer>();    
        List<Integer> list2 = new ArrayList<Integer>();    
        
        for(int i = 0; i < A.length; i++){
            list1.add(A[i]);    
        }
        Collections.sort(list1);
        
        for(int i = 0; i < B.length; i++){
            list2.add(B[i]);
        }
        Collections.sort(list2);
        
        for(int i = 0; i < list1.size(); i++){
            for(int j = list2.size()-1; j >= 0; j--){
                int temp = list1.get(i) * list2.get(j);
                answer += temp;
            }
        }
        return answer;
    }
}


  • 두번째 풀이 : 탐색할 때, 어떻게 동작할지 동작 과정 생각하기!
    • 중요!
import java.util.*;


class Solution
{
    public int solution(int[] A, int[] B)
    {
        int answer = 0;
        List<Integer> list1 = new ArrayList<Integer>();    
        List<Integer> list2 = new ArrayList<Integer>();    
        
        for(int i = 0; i < A.length; i++){
            list1.add(A[i]);    
        }
        Collections.sort(list1);
        
        for(int i = 0; i < B.length; i++){
            list2.add(B[i]);
        }
        Collections.sort(list2);
        
        int j = list2.size()-1;
        
        for(int i = 0; i < list1.size(); i++){
            for(; j >= 0; j--){
                int temp = list1.get(i) * list2.get(j);
                answer += temp;
                break;
            }
            j--;
 
        }
        return answer;
    }
}



5) 피보나치 수**

  • 첫번째 풀이 : 테케 절반만 통과함. 수정하기!
class Solution {
    public int solution(int n) {
        int answer = 0;
        int[] temp = new int[n+1];
        
        temp[0] = 0;
        temp[1] = 1;
        
        for(int i = 0; i < temp.length-2; i++){   
            temp[i+2] = temp[i] + temp[i+1];
            answer = temp[i+2];
        }
        answer = answer % 1234567;
        
        return answer;
    }
}


  • 두 번째 풀이 :
    • DP 개념 이용! 중요!**
class Solution {
    public int solution(int n) {
        int answer = 0;
        int[] temp = new int[n+1];
        
        temp[0] = 0;
        temp[1] = 1;
        
        // 더 쉬운 풀이! : DP 개념 이용!
        for(int i = 2; i < temp.length; i++){   
            temp[i] = (temp[i-1] + temp[i-2]) % 1234567;
        }
         
        return temp[n];
    }
}



6) 카펫**

  • 다시 풀기 : 생각하는 것이 까다롭다.


  • 첫 번째 풀이 : 다시 풀기! 76점 수준
    • 중간에 계산이 안맞는 경우가 있다. 이전 조합을 사용해야 할듯(‘-1’ 하기)
    • 예) 가로/ 세로 : 6/4 -> 8/3
    • 따라서, (가로길이 - 2) * (세로길이 - 2) == yellow 조건 고려하기!
      • yellow 계산이 안 맞을 수도
import java.util.*;

class Solution {
    public int[] solution(int brown, int yellow) {
        
        int sum = brown + yellow;
        List<Integer> list = new ArrayList<>();
        int[] answer = new int[2];
        
        for(int i = 0; i < sum; i++){
            if(sum % (i+1) == 0){
                list.add(i+1);
            }
        }
        
        for(int i = 0; i < 2; i++){
            if(list.size() % 2 != 0)
                answer[i] += list.get(list.size()/2);
            else{
                    answer[i] += list.get(list.size()/2-i);
                }
        }
        
              
        return answer;
    }
}


  • 두 번째 풀이 :
    • 등호 조건 주의, 그림을 직접 그려보면서 패턴을 정의해야 한다.
import java.util.*;

class Solution {
    public int[] solution(int brown, int yellow) {
        
        int sum = brown + yellow;
        int[] answer = new int[2];
        
        for(int i = 3; i < sum; i++){
            int j = sum / i;
            
            if((sum % i == 0) && j >= 3){
                int col = Math.max(i, j);
                int row = Math.min(i, j);
                
                if(yellow == ((col -2) * (row -2))){
                    answer[0] = col;
                    answer[1] = row;
                }
            }
        }
        
              
        return answer;
    }
}



7) 구명보트**

  • 첫 번째 풀이 : 다시 풀기! 테케 2개 중 1개만 통과

import java.util.*;

class Solution {
    public int solution(int[] people, int limit) {
        
        int answer = 0;
        int temp = limit;
        int sub = 0;
        Arrays.sort(people);
        
        for(int i = people.length-1; i >= 0; i--){
            sub = temp / people[i];  // 50 / 50 = 1
            
            for(int j = 0; j < people.length-1-i; j++){
                if(((sub-1) * people[j]) == people[j]){
                    answer++;
                    break;
                }
                
                sub = ((sub-1) * people[j]) % people[j];
                
                if(sub == 0){
                    answer++;
                    break;
                }
            }
            
        }
        return answer;
    }
}


  • 두 번째 풀이** :
    • 투 포인트로 찍어서 문제 풀이해보기!(그리디이긴 하지만 투포인터 이용)
    • sum하고 limit 차이점이 중요!
import java.util.*;

class Solution {
    public int solution(int[] people, int limit) {
        
        int answer = 0;
        int sum = 0;
        int min = 0;
        
        Arrays.sort(people);
        
        for(int max = people.length-1; max >= min; max--){
            sum = people[max] + people[min];
            if(sum <= limit){
                min++;
            }
            answer++;
        }
        return answer;
    }
}



8) H-Index*

  • 첫 번째 풀이 : 테케는 통과지만 실행 시, 모든 테스트에서 에러 발생
import java.util.*;

class Solution {
    public int solution(int[] citations) {
        int answer = 0;
        int[] temp = new int[citations.length];
        int[] count = new int[citations.length];
        
        Arrays.sort(citations);        
        
        for(int i = 0; i < citations.length; i++) {
            temp[i] = citations[citations.length - i - 1];
        }
        
        // 순회하면서 특정 값 비교하여 카운트하고 카운트가 전체 개수의 절반 이상일 때, 정답!
        for(int i = 0; i < citations.length; i++) {
            for(int j = 0; j < citations.length; j++) {
                if(citations[j] >= temp[i]) {
                    count[i]++;
                }
            }
        }
        
        for(int i = 0; i < count.length; i++) {
            if(count[i] > (count.length/2)){
                answer = temp[i]; 
                break;
            }
        }
        
        return answer;
    }
}


  • 두 번째 풀이 : 문제 설명이 부족하지만, 예를 들어, [7,7,7,7,3]인 경우에
    • H-Index는 4가 출력되어야하므로 citations에 포함되지 않는 경우도 고려해야 한다.
    • 기존 코드에서 조건문만 수정하기. 항상 정답이 citations나 temp에 있는 것이 아니다!
import java.util.*;

class Solution {
    public int solution(int[] citations) {
        int answer = 0;
        int[] temp = new int[citations.length];
        int[] count = new int[citations.length];
        
        Arrays.sort(citations);        
        
        for(int i = 0; i < citations.length; i++) {
            temp[i] = citations[citations.length - i - 1];
        }
        
        // 순회하면서 특정 값 비교하여 카운트하고 카운트가 전체 개수의 절반 이상일 때, 정답!
        for(int i = 0; i < citations.length; i++) {
            for(int j = 0; j < citations.length; j++) {
                if(citations[j] >= temp[i]) {
                    count[i]++;
                }
            }
        }
        
        // 항상 정답이 citations나 temp에 있는 것이 아니다!
        for(int i = 0; i < count.length; i++) {
            if(temp[i] >= count[i]){
                answer = count[i]; 
            }
        }
        
        return answer;
    }
}



9) 1차 - 캐시

  • 첫 번째 풀이 : 어렵다.. LRU 알고리즘 구현하는 방법?
import java.util.*;

class Solution {
    public int solution(int cacheSize, String[] cities) {
        int answer = 0;
        
        // LinkedList 사용하거나 Queue 사용할 듯 
        List<String> city = new ArrayList<>();
        int temp = 0; 
        
        for(int i = 0; i < cities.length; i++){
            
            
            if(i % 3 == cacheSize-1){
                if(city.contains(cities[i])){
                    temp = i;
                    answer = answer + 5;
                    city.remove(0);
                }
            }
            city.add(cities[i]);
            answer++;
        }
        
        return answer;
    }
}


  • 두 번째 풀이 :




10) 의상**

  • 첫 번째 풀이 : 완전탐색 불가능
import java.util.*;

class Solution {
    public int solution(String[][] clothes) {
        int answer = 0;
        int count = 0;
        Map<String, String> hashMap = new HashMap<String, String>();
        
        for(int i = 0; i < clothes.length; i++){
            hashMap.put(clothes[i][0], clothes[i][1]);
        }
        for(int i = 0; i < hashMap.size(); i++){
            for(int j = 0; j < hashMap.size(); j++){
                if(hashMap.get(clothes[i][0]) != "face"){
                    if(hashMap.get(clothes[i][0]) != clothes[j][1]){
                        count++;
                        break;
                    }
                }
                else{
                    break;
                }
            }
            break;
        }
        System.out.println(count);
        for(int i = 0; i < hashMap.size(); i++){
            for(int j = 0; j < hashMap.size(); j++){
                if(count == 0){
                    if(hashMap.get(clothes[i][0]) == clothes[i][1]){
                        answer++;
                    }
                }
                else{
                    if(hashMap.get(clothes[i][0]) != "face"){
                        if(hashMap.get(clothes[i][0]) == clothes[j][1]){
                            answer += Math.pow(hashMap.size()- count , (hashMap.size() - count));
                        }
                        else{
                            answer++;
                        }
                    }
                }
            }
        }
        
        return answer;
    }
}


  • 두 번째 풀이** : stream API 공부하기!!
    • stream API : test.stream().reduce(1, (a,b) -> a*b)
      • stream의 reduce는 초기값을 ‘1’로 설정할 수 있고 스트림의 모든 요소를 반복적으로 처리할 수 있다.
      • 옷 종류에 관한 경우의 수를 정리해서 Map 형식으로 다시 매핑해서 카운팅한다.
      • 이 경우에는 옷을 안입는 경우의 수를 모두 하나씩 더하고 나서 마지막에 모두 안 입는 경우를 1개 뺀다.(적어도 한가지 정도는 입어야하니까)
      • 이펙티브 자바 공부하기!!**
import java.util.*;

class Solution {
    public int solution(String[][] clothes) {
        int answer = 0;
        Map<String, Integer> hashMap = new HashMap<String, Integer>();
        
        for(int i = 0; i<clothes.length; i++){
            hashMap.put(clothes[i][1], hashMap.getOrDefault(clothes[i][1],1) + 1);
        }
        
        Collection<Integer> test = hashMap.values();
        answer = test.stream().reduce(1, (a,b) -> a*b) - 1;
        // (a, b)를 "(a+1) * (b+1) - 1" 로 풀기 
        // 이것은 옷을 안입는 경우의 수를 모두 하나씩 더하고 나서 마지막에 모두 안입는 경우를 1개 뺀다.
        // 적어도 한가지 정도는 입어야하니까
         
        return answer;
    }
}



11) 기능개발**

  • 첫 번째 풀이 : 테케 모두 통과하지만, 런타임 에러 발생!
    • Iterator의 iterator.hasNext() 사용에서 런타임 에러 발생한듯!
import java.util.*;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {
        
        int[] temp = new int[speeds.length];
        
        Queue<Integer> queue1 = new LinkedList<Integer>();
        Queue<Integer> queue2 = new LinkedList<Integer>();
        
        for(int prog : progresses){
            queue1.add(100 - prog);
        }
        for(int i = 0; i < speeds.length; i++){
       
            int temp2 = queue1.poll();
            int temp3 = temp2 / speeds[i];
            
            if(temp2 % speeds[i] != 0){
                queue2.add(temp3+1);
            }
            else{
                queue2.add(temp3);
            }
            
        }
        
        int count = 1;
        // 주의** : Queue는 poll하면 remove되기 때문에 for문에서 index가 사라진다.
        // 그래서 Iterator 이용하기!!
        
            Iterator iter = queue2.iterator();
            Iterator iter2 = queue2.iterator();
        
            int temp4 = (int) iter.next();
            int i = 0;
            int count2 = 1;
        
            int temp6 = (int) iter2.next();
        
            while(iter2.hasNext()){
                int temp7 = (int) iter2.next();
                
                if(temp7 > temp6){
                    count2++;
                }
            }
        
            int[] answer = new int[count2];
        
            while(iter.hasNext()){
               
               int temp5 = (int) iter.next();
                
                if(temp4 > temp5){
                    count++;
                }
                else{
                    temp4 = temp5;
                    System.out.println(temp4);
                    answer[i] = count;
                    i++;
                    count = 1;
                    
                    if(!iter.hasNext()){
                      answer[i] = 1;
                    }
                }
                
                if(!iter.hasNext()){
                    answer[i] = count;
                }
                
            }
            
        
        return answer;
    }
}



  • 두 번째 풀이 ; Iterator 빼고 Queue, ArrayList로만 다시 풀기
    • 위와 로직이 같지만, queue의 peek(), poll() 이용하기!

import java.util.*;

class Solution {
    public int[] solution(int[] progresses, int[] speeds) {

        ArrayList<Integer> list = new ArrayList<>();
        Queue<Integer> q = new LinkedList<>();

        for (int i = 0; i < progresses.length; i++) {
            if ((100 - progresses[i]) % speeds[i] == 0) {
                q.add((100 - progresses[i]) / speeds[i]);
            } else {
                q.add((100 - progresses[i]) / speeds[i] + 1);
            }
        }

        int x = q.poll();
        int count = 1;
        while (!q.isEmpty()) {
            if (x >= q.peek()) {
                count++;
                q.poll();
            } else {
                list.add(count);
                count = 1;
                x = q.poll();
            }
        }
        list.add(count);

        int[] answer = new int[list.size()];
        for (int i = 0; i < answer.length; i++) {
            answer[i] = list.get(i);
        }


        return answer;
    }
}



12) 프로세스**

  • 첫 번째 풀이 : queue 순서 조작하기!, 테케 1개 통과함. 다시 풀기
    • 큐, 우선순위 큐
import java.util.*;

class Solution {
    public int solution(int[] priorities, int location) {
        
        // 값을 비교해서 가장 높은 값이면 비교해서 같으면, 빼서 뒤로 보내기!
        // peek로 비교해서 poll하고 add하기
        // priorities와 queue를 비교하기!

        int answer = 0;
        int temp = 0;
        int temp2 = 0;
        int count = 0;
        
        Queue<Integer> queue = new LinkedList<Integer>();
        PriorityQueue<Integer> queue2 = new PriorityQueue<Integer>();
        
        for(int pri : priorities){
            queue.add(pri);
        }
        for(int pri2 : priorities){
            queue2.add(pri2);
        }
        
        for(int i = 0; i < priorities.length; i++){
            temp = queue2.poll();
        }
        
        int temp6 = 0;
        
        for(int i = 0; i < priorities.length; i++){
            
            temp2 = queue.peek();
            
            // 가장 큰 숫자인지 비교해서 index 담기!!
            if(temp2 == temp){
                count = count + i;
                break;
            }
            else if(temp2 != temp){
                int temp3 = queue.poll();
                count = 1;
                if(temp6 == temp3)
                    count++;
                
                temp6 = temp3; 
                
                queue.add(temp2);
               
            }
        }

        for(int i = 0; i < priorities.length; i++){
            int temp4 = priorities[location];   
            // priorities : 2, 1, 3, 2
            // queue : 3, 2, 2, 1
            
            int temp5 = queue.poll();
            
            if(temp4 != temp5){
                answer++;
            }    
                
            else if(temp4 == temp5){
              
                while(count != answer){
                    answer++;
                }
                answer++;
                return answer;
                
            }
        }
        
        return answer;
    }
}



  • 두 번째 풀이 : 우선순위 큐로 다시 풀기
    • 거의 로직은 비슷한거 같은데 index 컨트롤 하는 것 다시 생각하기
    • 암기하기, 우선순위큐를 이용하는 방법!


  • if(queue2.peek() == priorities[i]){} : 이 부분 중요
    • 최대값부터 다시 시작하겠다는 뜻


  • 중요!! :
    • 우선순위큐는 중복값을 허용하고 우선순위가 같은 경우에 값이 같다면 그들은 큐에서 그들의 순서에 의해 처리된다.
      • 우선순위가 같고 값이 같은 상황에서는 일단, 순서대로 처리가 이루어진다.
import java.util.*;

class Solution {
    public int solution(int[] priorities, int location) {
        
        // peek로 비교해서 poll하고 add하기
        // priorities와 queue를 비교하기!

        int answer = 0;

        Queue<Integer> queue = new LinkedList<Integer>();
        PriorityQueue<Integer> queue2 = new PriorityQueue<Integer>(Collections.reverseOrder());
        
        for(int pri2 : priorities){
            queue2.add(pri2);
        }
        
        while (!queue2.isEmpty()) {
            for(int i = 0; i < priorities.length; i++){
             
                if(queue2.peek() == priorities[i]){

                    if(i == location){
                        answer++;
                        return answer;
                    }
                    queue2.poll();
                    answer++;
                }
            }
        }

        return -1;
    }
}



13) 타겟 넘버**

  • 첫 번째 풀이 : boolean 값을 이용했는데 실패해서 DFS 개념 이용하기!
class Solution {
    public int solution(int[] numbers, int target) {
        int answer = 0;
        int temp = 0;
        boolean[] chk = new boolean[numbers.length];
        
        for(int i = 0; i < numbers.length; i++){
            if(chk[i] && target < temp)
                temp += numbers[i];
            else{
                temp -= numbers[i];
            }
            chk[i] = !chk[i];
            
        }
        
        return answer;
    }
}



  • 두 번째 풀이 : DFS 개념 이용하기
    • DFS, BFS를 이용한 완전 탐색 문제를 풀 때는 항상 무엇을 탐색의 대상으로 삼아야 하는지에 대한 기준을 내리지 못해 삽질을 많이 하는 것 같다. 완전탐색을 이용해 모든 경우의 수를 고려하면 된다.
    • 생각보다 간단한 문제였다. 경우의 수를 생각하기 때문에 plus, minus의 경우를 모두 따진다.
    • 중요** : DFS, 재귀함수, 완전탐색이라서 for 반복문 사용 안 해도 되고 ‘수행조건’이랑 ‘탈출조건’만 설계하면 된다.
class Solution {
    int answer = 0;
    
    public int solution(int[] numbers, int target) {
        dfs(numbers, 0, target, 0);
        return answer;
    }
    
    public void dfs(int[] numbers, int depth, int target, int sum) {
        
        if(depth == numbers.length){
            if(target == sum)
                answer++;
        }
        else{
            dfs(numbers, depth+1, target, sum + numbers[depth]);
            dfs(numbers, depth+1, target, sum - numbers[depth]);           
        }


    }
}



14) 전화번호 목록

  • 첫 번째 풀이 : 75점 풀이, 수정하기!
import java.util.*;

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;
        
        for(String phone : phone_book){
            list.add(phone);
        }

        for(int i = 0; i < phone_book.length; i++){
            for(int j = 0; j < phone_book.length; j++){
                if(i != j){
                    
                    if(phone_book[i].contains(phone_book[j])){
                        System.out.println(phone_book[j]);
                        answer = false;
                        return answer;
                    }
                    else{
                        answer = true;
                    }
                }
            }
        }

        return answer;
    }
}



  • 두 번째 풀이** :
    • 효율성 테스트** : Arrays.sort로 정렬 후 바로 뒤의 index만 비교하면, 훨씬 효율적이다.
    • startsWith() : 대상 문자열이 특정 문자 또는 문자열로 시작하는지 체크하는 함수이다.
    • contains() : 대상 문자열에 특정 문자열이 포함되어 있는지 확인하는 함수이다.
    • String 은 정렬하면 사전순으로 정렬되기 때문에, 따라서 무조건 앞의 변수만 비교하면 되기 때문에 for 문 한번으로 끝낼 수 있습니다.


  • 문자열이 그대로 일치하는 것을 찾는 문제가 아니기 때문에 contains() 보다는 startsWith()를 사용한다.
import java.util.*;

class Solution {
    public boolean solution(String[] phone_book) {
        boolean answer = true;

        Arrays.sort(phone_book);
            
        for(int i = 0; i < phone_book.length-1; i++){
            if(phone_book[i+1].startsWith(phone_book[i])){
                System.out.println(phone_book[i+1]);
                answer = false;
                break;
            }
        }
        
        return answer;
    }
}



15) 더 맵게

  • 첫 번째 풀이 : 테케 통과했지만 50점 풀이, 효율성 테스트 다시
import java.util.*;

class Solution {
    public int solution(int[] scoville, int K) {
        int answer = 0;
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        
        for(int scov : scoville){
            pq.add(scov);
        }
        
        for(int i = 0; i < pq.size(); i++){
            if(!pq.isEmpty()){
                if(pq.peek() < K){
                    if(pq.size() >= 2){
                        pq.add(pq.poll() + (pq.poll() * 2));
                    }
                    answer++;
                }
            }
        }
        
        if(pq.peek() < K){
            return -1;
        }
        
        return answer;
    }
}



  • 두 번째 풀이 : 위의 풀이보다 훨씬 더 간단하다.
    • pq.peek()는 초기에 for문보다는 while문으로만 비교하고 pq.size()로 최종 비교
import java.util.*;

class Solution {
    public int solution(int[] scoville, int K) {
        int answer = 0;
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        
        for(int scov : scoville){
            pq.add(scov);
        }
        
        while(pq.peek() < K){
            if(!pq.isEmpty()){
               if(pq.size() < 2){
                    return -1;
                }
                
                pq.add(pq.poll() + (pq.poll() * 2));
                answer++;
            }
        }
        
        return answer;
    }
}



16) 주식가격

  • 앞으로 문제 푸는 방법 -> 유형별로 lv.2 : 10개, lv.3 : 12개 풀고 다시 lv.2 Kakao 풀기

  • 이 문제는 이해하는 것이 어렵다.

    • 주식 가격이 전체 가격 중에서 이후 시간에 해당 가격으로부터 떨어지지 않는 시간을 return하는 문제이다.


  • 첫 번째 풀이 : index 이용해서 푸는 방법
import java.util.*;

class Solution {
    public int[] solution(int[] prices) {
        int[] answer = new int[prices.length];
        
        for(int i = 0; i < prices.length; i++){
            for(int j = i+1; j < prices.length; j++){
                if(prices[i] <= prices[j]){
                    answer[i]++;
                }
                else{
                    answer[i]++;
                    break;
                }
            }
        }

        return answer;
    }
}



  • 두 번째 풀이 : stack 이용해보기 출처
    • 주식가격이 떨어지지 않는 구간에는 일단 스택에 index(시간 카운트)를 넣어주고 주식가격이 떨어지는 구간에는 ‘현재시간-초기시간’ 계산식 진행
class Solution {
    public int[] solution(int[] prices) {
        int[] ans = new int[prices.length];
        Stack<Integer> stack = new Stack();

        for (int i = 0; i < prices.length; i++) {
            while (!stack.isEmpty() && prices[i] < prices[stack.peek()]) {
                ans[stack.peek()] = i - stack.peek();
                stack.pop(); // 답을 구했기 때문에 stack에서 제거한다
            }
            stack.push(i);
        }

        while (!stack.isEmpty()) { // 값을 구하지 못한 index == 끝까지 가격이 떨어지지 않은 주식
            ans[stack.peek()] = prices.length - stack.peek() - 1;
            stack.pop();
        }

        return ans;
    }

}



17) 다리를 지나는 트럭

  • 첫 번째 풀이 : 수정하기
import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        int answer = 0;
        int temp = 0;
        int poll = 0;
        Queue<Integer> queue = new LinkedList<>();
        
        for(int truck : truck_weights){
            queue.add(truck);
        }
        
        for(int i = 0; i < queue.size(); i++){
           
            if(queue.peek() < weight){

                if((weight >= temp + queue.peek())){
                    
                }
                else{
                    temp = 0;
                    answer += bridge_length;
                }
                poll = queue.poll();
                temp = poll + temp;

            }    
            // if(i == queue.size()-1){
            //     answer += poll;
            // }
        }
        
        return answer;
    }
}



  • 두 번째 풀이_1 : 어렵다
    • 대기하는 트럭을 queue에 따로 저장하지 않고 truck_weight 배열을 활용해서 index를 만들고 1씩 더하는 방법을 사용하면 조금 더 효율적일 것
import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
           int answer = 0;


            Queue<Integer> bridgeQue = new LinkedList<>();
            Queue<Integer> readyTruckQue = new LinkedList<>();

            // 초기 다리 상태 세팅
            for(int i = 0 ; i<bridge_length ; i++)
            {
                bridgeQue.offer(0);
            }


            // 대기 트럭 세팅
            for(int i : truck_weights)
            {
                readyTruckQue.offer(i);
            }

            int time = 0;
            int totalWeight = 0;
            
            while(!bridgeQue.isEmpty())
            {
                // while 한번 도는게 1초라고 생각 
                // 시작하자마자 다리 맨 마지막부분에서 트럭을 빼버림
                totalWeight -= bridgeQue.peek();
                bridgeQue.poll();

                // 대기 트럭열에 있던 마지막 트럭이 다리에 올라가면, 다리 길이 만큼의 시간 후에  
                // 마지막 트럭이 다리를 건너기때문에 다리 길이(*1초) 만큼 시간이 소요되면 모든 트럭이 건너게 됨.
                if(readyTruckQue.isEmpty())
                {
                    time += bridge_length;
                    break;
                }
                else
                {
                    // 다리의 하중량을 버틸 수 있으면 트럭 투입
                    if((totalWeight+readyTruckQue.peek()) <= weight)
                    {
                        bridgeQue.offer(readyTruckQue.peek());
                        totalWeight+=readyTruckQue.peek();
                        readyTruckQue.poll();
                    }
                    // 다리의 하중량때문에 트럭 못들어가면 0으로 넣어줌
                    else {
                        bridgeQue.offer(0);
                    }
                }
                time++;
            }
            answer = time;

            return answer;
    }
}


  • 두 번째 풀이_2 : 어렵다
import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        int answer = 0;
        Queue<Integer> bridge = new LinkedList<>(); 
		// 비어있는 다리의 공간을 0으로 가득 채웠다.
        for(int i=0;i<bridge_length;i++){
            bridge.offer(0);
        }
        
        int index = 0;
        // 다리에 있는 현재 트럭의 무게이다.
        int currentWeight = 0;
        // 트럭이 더이상 남아있지 않을 때 탈출해주기 위해 조건을 만들었다.
        while(index < truck_weights.length){
        	// 현재 다리에 있는 트럭무게에서 곧 나갈 트럭의 무게를 빼준다.
            currentWeight -= bridge.poll();
            // 새 트럭이 들어올 것이므로 1초를 추가한다.
            answer++;
            // 현재 다리에 있는 트럭 무게와 곧 들어올 트럭 무게의 합과 다리의 하중을 비교
            if(currentWeight + truck_weights[index] <= weight){
            	// 무게를 버틴다면 다리에 트럭을 추가한다.
                bridge.offer(truck_weights[index]);
                // 현재 다리에 있는 트럭 무게에도 새 트럭 무게를 더해준다.
                // 그리고 다음 트럭을 지정하기 위해 후위 연산자를 써주어 index를 증가시켰다.
                currentWeight += truck_weights[index++];
            } else{
            	// 버티지 못한다면 0을 추가한다.
                bridge.offer(0);
            }
        }
        //처음 설정한 0으로 채워진 다리가 전부 치환되면 결국 처음 다리 길이와 같으므로
        //트럭이 지나간 시간 + 다리 길이
        return answer + bridge_length; 
    } 
}


  • 두 번째 풀이_2 : 최종 정리
import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        int answer = 0;
        int temp = 0;
        Queue<Integer> queue = new LinkedList<>();
        
        for(int i = 0; i < bridge_length; i++){
            queue.add(0);
        }
        
        int i = 0;
        
        while(i < truck_weights.length){
            temp -= queue.poll();
            answer++;
            
            if(temp + truck_weights[i] <= weight){
                queue.add(truck_weights[i]);
                temp += truck_weights[i++];
            }    
            else{
                queue.add(0);
            }
        
        }
        
        return answer + bridge_length;
    }
}



18) 큰 수 만들기

  • 첫 번째 풀이 : 다시 풀기
import java.util.*;

class Solution {
    public String solution(String number, int k) {
        String answer = "";
        
        String[] nums = number.split("");
        int count = 0;
        
        List<Integer> list = new ArrayList<Integer>();

        for(String num : nums){
            list.add(Integer.parseInt(num));
        }
        
        for(int i = 1; i < list.size(); i++){
            if(list.get(i-1) > list.get(i)){
                answer += list.get(i-1);
            }
            
            if(list.get(i-1) < list.get(i)){
                count++; 
                continue;
            }

            if(count == k){
                return answer;
            }
           
        }
        
        return answer;
    }
}




  • 두 번째 풀이 :
    • index에는 가장 큰 수 다음 index를 넣어준다. 이유는 그 다음 문자열부터 가장 큰 수를 찾아야 하기 때문이다.
    • index 주의!! 여러 번 풀기!! 그리디는 내가 생각하는 방법과 반대 방향으로 문제를 풀어야 한다.
    • 제거하지 않고 index를 조회하는 방식으로 풀이!
    • 참고
import java.util.*;

class Solution {
    public String solution(String number, int k) {
        StringBuilder sb = new StringBuilder();
        int index = 0;
        int max = 0;
        
        for(int i=0; i < number.length() - k; i++) {
            max = 0;
            for(int j = index; j <= k+i; j++) {
                if(max < number.charAt(j)-'0') {
                    max = number.charAt(j)-'0';
                    index = j+1;
                }
            }
            sb.append(max);
        }
        return sb.toString();
    }
}



19) 가장 큰 수

  • 첫 번째 풀이 : 수정하기
    • 메모리 에러
import java.util.*;
import java.lang.Math;

class Solution {
    public String solution(int[] numbers) {
        String answer = "";
        String temp = "";
        int tempNum = -1;
        List<Integer> temp1 = new ArrayList<>();
        String[] temps = new String[(int)Math.pow(2, numbers.length)];
        List<String> temp2 = new ArrayList<>();

        for(int i = 0; i < (int)Math.pow(2, numbers.length); i++){
            for(int j = 0; j < numbers.length; j++){
                if(tempNum != j){
                    temp1.add(numbers[j]);
                }
                else
                    continue;
                
                if(temp1.size() != numbers.length){
                    j = 0;
                }
                else
                    break;
                
            }
            tempNum = i;
            
            for(Integer num : temp1){
                if(!num.equals(null))
                    temp += String.valueOf(num);
            }
            temps[i] = temp;
        }
        
        for(String num1 : temps){
            if(!num1.equals(null))
                temp2.add(num1);
        }
        
        Collections.sort(temp2);
        
        answer = temp2.get(temp2.size()-1);
        
        return answer;
    }
}



  • 두 번째 풀이 : Comparator, StringBuilder 이용!
    • 숫자들의 앞자리 숫자가 큰 수가 먼저 와야 가장 큰 수를 만들 수 있기 때문에 이를 기준으로 내림차순으로 숫자를 정렬!
    • 내림차순하는 방법 : Collections.sort() 보다는 다른 방식 이용하기!**


  • Arrays.sort() 내부에서 Comparator의 compareTo()를 이용하는 방식!
    • 내림차순 : (o2+o1).compareTo(o1+o2);
    • 오름차순 : (o1+o2).compareTo(o1+o2);


  • 정렬된 숫자를 이어붙이는 경우, String 값을 더하는 것보다 StringBuilder 이용해 append()하는 것을 추천!
    • 이유는 String은 Immutable(불변 객체)이기 때문이다. String을 합치는 연산이 많을수록 StringBuilder가 유리하다.
import java.util.*;

public class Solution {
    public String solution(int[] numbers) {
        String[] arr = new String[numbers.length];

        for (int i = 0; i < arr.length; i++) {
            arr[i] = String.valueOf(numbers[i]);
        }

        Arrays.sort(arr, (o1, o2) -> (o2 + o1).compareTo(o1 + o2));
        
        if (arr[0].equals("0")) {
           return "0";
        }

        StringBuilder answer = new StringBuilder();

        for (int i = 0; i < arr.length; i++) {
            answer.append(arr[i]);
        }


        return answer.toString();
    }
}



20) 소수 찾기

  • 첫 번째 풀이 : dfs 이용하기


  • 중요 개념 정리 :
    • split가 아니라 substring 이용하기
    • ‘1, 7, 17, 71’ 구조를 만드는 방법 중요!!
      • set으로 이전 값 중복 제거
import java.util.*;

class Solution {
    public int solution(String numbers) {
        
        Set<Integer> set = new HashSet<>();
        dfs(numbers, "", set);
        int answer = 0;
        
        for(Integer num : set){
            int i;
            for(i = 2; i < num ; i++){
                if(num % i == 0){
                    break;
                }
            }
            if(i == num){
                answer++;
            }
        }
        
        return answer;
    }
    
    public void dfs(String numbers, String temp, Set<Integer> set) {
        int length = numbers.length();
        
        // '1, 7, 17, 71' 구조를 만드는 방법(set으로 중복 제거)
        if(!"".equals(temp)){
            set.add(Integer.valueOf(temp));
        }
        
        for(int i = 0; i < length; i++){
            dfs(numbers.substring(0, i) + numbers.substring(i+1, length),
                temp + numbers.charAt(i),
               set);
        }
        
    }
}



  • 두 번째 풀이 : 백트래킹 이용하여 다시 풀어보기!!
    • 방문했는지 판단하기(boolean[])
import java.io.*;
import java.util.*;
class Solution {
    static ArrayList<Integer> arr = new ArrayList<>();
    static boolean[] check = new boolean[7];
    
    public int solution(String numbers) {
        int answer = 0;
        for(int i=0; i<numbers.length(); i++){
            dfs(numbers,"",i+1);
        }
        
        for(int i=0; i<arr.size(); i++){
            if(prime(arr.get(i))) answer++;              
        }
        
        return answer;
  
    }
	//백트래킹
	static void dfs(String str, String temp, int m) {
            if(temp.length() == m){
                int num = Integer.parseInt(temp);
                if(!arr.contains(num)){
                    arr.add(num);
                }
            }
        
            for(int i=0; i<str.length(); i++){
                if(!check[i]){
                    check[i] = true;
                    temp += str.charAt(i);
                    dfs(str, temp, m);
                    check[i] = false;
                    temp = temp.substring(0, temp.length()-1);
                }
            }
		
	}
	//소수 판단
	static boolean prime(int n) {
		if(n<2) return false;
		
		for(int i=2; i*i<=n; i++) {
			if(n % i == 0) return false;
		}
		
		return true;
	}

}



2. Lv.3

1) 네트워크**

  • 첫 번째 풀이 : BFS 이용하기
    • 반복해서 암기하기! BFS 기본 문제
    • 기존에 queue에서 poll이 되고나서 start 위치 빼고나서도 완전 탐색을 위해서 또 다시 나머지 위치도 방문!!

import java.util.*;

class Solution {
    static boolean[] visited;

    public int solution(int n, int[][] computers) {
        int answer = 0;
        
        visited = new boolean[n];
        
        for(int i = 0; i < n; i++){
            if(visited[i] == false){
                bfs(i, computers, n);
                answer++;
            }
        }
        return answer;
    }
    
    public void bfs(int i, int[][] computers, int n){
        
        Queue<Integer> queue = new LinkedList<>();
        queue.add(i);
        visited[i] = true;
        
        while(!queue.isEmpty()){
            int value = queue.poll();
            
            // 위에서 poll되어서 start 위치 빼고 완전 탐색을 위해서 나머지도 위치 방문!!
            for(int j = 0; j < n; j++){
                if(visited[j] == false && computers[value][j] == 1){
                    visited[j] = true;
                    queue.add(j);
                }
            }
        }
    }
}


  • 두 번째 풀이 : DFS 이용하기
    • 메인에서 로직이 돌아 한 번 탐색하여 answer에 1을 더한다. 그리고나서 완전 탐색을 위해 한번 더 탐색한다.
    • answer에 1을 더하고 난 후 DFS 깊이 탐색에서는 answer에 1을 더하지 않는다. 네트워크가 연결되어 있는 모든 것은 1개로 생각하기 때문이다.
import java.util.*;

class Solution {
    static boolean[] visited;

    public int solution(int n, int[][] computers) {
        int answer = 0;
        
        visited = new boolean[n];
        
        // 2. dfs
        for(int i = 0; i < n; i++){
            if(visited[i] == false){
                dfs(i, computers, n);
                answer++;
                visited[i] = true;
            }
        }
      
        return answer;
    }
    
    public void dfs(int i, int[][] computers, int n){
        
        // 메인에서 로직이 돌아서 한 번  탐색하여 answer에 1을 더하고나서 
        // 완전 탐색을 위해 한번 더 탐색한다.
        visited[i] = true;
        
        for(int j = 0; j < n; j++){
            if(visited[j] == false && computers[i][j] == 1){
                dfs(j, computers, n);
            }
        }
    }
}



2) 베스트앨범

  • 첫 번째 풀이 : 다시 수정, 최적화하기
import java.util.*;

class Solution {
    public int[] solution(String[] genres, int[] plays) {
        
        // List
        List<String> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        
        // Map<genres, plays>
        Map<String, Integer> hsMap = new HashMap<>();
        
        // Set
        Set<String> hsSet = new HashSet<>();
        
        /* 초기화 */
        for(int i = 0; i < genres.length; i++){
            list1.add(genres[i]);
            list2.add(Integer.valueOf(plays[i]));
            hsSet.add(genres[i]);
        }
        
        /* 장르별 크기 합 구하기 */
        for(String genre : hsSet){
            Integer temp = 0;
            for(int i = 0; i < genres.length; i++){
                
                if((genre.equals(list1.get(i)))){
                    temp += list2.get(i);
                }
            }
            hsMap.put(genre, temp);
        }
        
        System.out.println(hsMap.get("pop"));

        /* 장르별 크기 순 정렬 */
        List<String> listSort = new ArrayList<>();
        String genre1 = "";
        for(String genre : hsSet){

            if(genre1 == ""){
                genre1 = genre;
                continue;
            }
            
            if(hsMap.get(genre1) > hsMap.get(genre)){
                listSort.add(genre1);
                listSort.add(genre);
            }
            else{
                listSort.add(genre);
                listSort.add(genre1);
            }
        }
        
        int[] answer = new int[listSort.size() * 2];
        
        // Collections.sort(list1, (o1, o2) -> (o2+o1).compareTo(o1+o2));
        // Collections.sort(list2, (o1, o2) -> (o2+o1).compareTo(o1+o2));
        // Collections.reverse(list2);
        Map<String, Integer> hsMap1 = new HashMap<>();
        int[] temp1 = new int[listSort.size() * 2];
        int[] temp2 = new int[2];
        
        /* 장르 내 많이 재생된 노래순 정렬 */
        /* 추가 : 같은 값일 경우 처리하기 */
        for(int i = 0; i < listSort.size(); i++){
            int count = 0;
            for(int j = 0; j < answer.length; j++){
                if(listSort.get(i).equals(list1.get(j))){
                    if(count == 2){
                        break;
                    }
                    temp1[j] += list2.get(j);
                    count++;
                }
                System.out.println(temp1[j]);
            }
        }
        
        for(int i = 0; i < plays.length; i++){
            for(int j = 0; j < answer.length; j++){
                if(plays[i] == temp1[j]){
                    answer[i] += j;
                }
            }
        }
        
        return answer;
    }
}



3) 단어 변환

a. 수정하기

  • 방문 배열 추가, 한 문자만 다른 것 체크하는 로직 추가
import java.util.*;

class Solution {
    public int solution(String begin, String target, String[] words) {
        int answer = 0;
        int depth = 0;
        dfs(begin, target, words, depth);
        answer = depth;
        return answer;
    }
    
    // 수정하기 : 방문 배열 추가, 한 문자만 다른 것 체크하는 로직 추가
    public void dfs(String begin, String target, String[] words, int depth){
        
        for(int i = 0; i < words.length; i++){
            if(!begin.equals(target)){
                begin = words[i++];
                dfs(begin, target, words, depth);
            }
        }
    }
}



b. 수정하기2

  • static 변수 선언 주의!
    • java라서 여러 번 타고 들어간다.
import java.util.*;

class Solution {
    static int answer = 0;
    static int depth = 0;
    static boolean[] visited;
    
    public int solution(String begin, String target, String[] words) {
        visited = new boolean[words.length];
        dfs(begin, target, words, 0);
        
        return answer;
    }
    
    public static boolean oneDiffCheck(String word1, String word2){
        int count = 0;
        
        for(int i = 0; i < word1.length(); i++){
            if(word1.charAt(i) != word2.charAt(i)){
                count++;
            }
        }
        
        if(count == 1){
            return true;
        }
        else
            return false;
    }
    
    // 방문 배열 추가, 한 문자만 다른 것 체크하는 로직 추가
    public static void dfs(String begin, String target, String[] words, int depth){
        if(answer <= depth){
            return ;
        }
        
        if(begin.equals(target)){
            answer = depth;
            return ;
        }
        
        for(int i = 0; i < words.length; i++){
            if(oneDiffCheck(begin, words[i]) && !visited[i]){
                visited[i] = true;
                dfs(words[i], target, words, depth+1);
                visited[i] = false;
            }
        }
    }
}



c. 최종 코드!!

  • 완전탐색으로 하면서, depth 카운팅!
    • 일치하지 않을 경우도 추가로 생각해줘야한다! 50인 경우는 문제 조건에서 words에는 3개이상 50개 이하의 단어가 존재해서 ‘50’으로 설정함.
import java.util.*;

class Solution {
    static int answer = 50;
    static boolean[] visited;
    
    public int solution(String begin, String target, String[] words) {
        visited = new boolean[words.length];
        dfs(begin, target, words, 0);
        
        if(answer == 50){
            return 0;
        }
        
        return answer;
    }
    
    public static boolean oneDiffCheck(String word1, String word2){
        int count = 0;
        
        for(int i = 0; i < word1.length(); i++){
            if(word1.charAt(i) != word2.charAt(i)){
                count++;
            }
        }
        
        if(count == 1){
            return true;
        }
        else
            return false;
    }
    
    // 방문 배열 추가, 한 문자만 다른 것 체크하는 로직 추가
    public static void dfs(String begin, String target, String[] words, int depth){
        if(answer <= depth){
            return ;
        }
        
        if(begin.equals(target)){
            answer = depth;
            return ;
        }
        
        for(int i = 0; i < words.length; i++){
            if(oneDiffCheck(begin, words[i]) && !visited[i]){
                visited[i] = true;
                dfs(words[i], target, words, depth+1);
                visited[i] = false;
            }
        }
    }
}



4) 등굣길

a. 수정하기


import java.util.*;

class Solution {
    
    static int[][] D;
    static boolean[][] visited;
    
    public int solution(int m, int n, int[][] puddles) {
        int answer = 0;
        visited = new boolean[m][n]; 
        
        D = new int[m][n];
        
        for(int i = 1; i < n+1; i++){
            for(int j = 1; j < m+1; j++){
                if((D[j][i] != puddles[j][i]) && !visited[j][i]){
                    D[j][i] = D[j-1][i-1] + 1;
                    visited[j][i] = true;
                    answer++;
                }
            }
        }
        return answer;
    }
}



b. 최종 코드

  • index 정의하는 것, 정답 맞추는 형식에 관한 조건 주의!!,
    • 문제 잘 읽기!


  • 경로 찾기 : 알고리즘 생각!
    • 최단 거리, 경우의 수


  • Dp라서 점화식으로 해석하기!!
    • puddles를 재정의 하는 것이 까다로움.
    • 문제 조건에서 행/열이 순서 바뀐 것 주의!
import java.util.*;

class Solution {
    static int[][] D;
    
    public int solution(int m, int n, int[][] puddles) {
        int answer = 0;
        D = new int[n+1][m+1];
        
        for(int i = 0; i < puddles.length; i++){
            int x = puddles[i][0];
            int y = puddles[i][1];
            D[y][x] = -1;
        }
        
        D[1][1] = 1;
        for(int i = 1; i < n+1; i++){
            for(int j = 1; j < m+1; j++){
                if(D[i][j] == -1){
                    continue;
                }
                if(D[i][j-1] != -1){	// y축 이동!!
                    D[i][j] += D[i][j-1];
                }
                if(D[i-1][j] != -1){	// x축 이동!!
                    D[i][j] += D[i-1][j];
                }
                
                D[i][j] %= 1000000007;
            }
        }
        
        answer = D[n][m] % 1000000007;
        return answer;
    }
}



5) 여행경로

a. 수정하기

  • 좀 더 간단한 방법이 있을 것 같다.
    • 현재는 너무 복잡하다.
import java.util.*;

class Solution {
    
    static String[] A;
    static String[] B;
    static String[] answer;
    static int depth;
    static Stack<String> stack;
        
    public String[] solution(String[][] tickets) {
        A = new String[tickets.length + 1];
        B = new String[tickets.length + 1];
        stack = new Stack<String>();
        depth = 0;
        int count = 0;
        
        for(int i = 0; i<tickets.length; i++){
            A[i+1] = tickets[i][1];
            B[i+1] = tickets[i][0];
            
            if(A[i+1].equals("ICN")){
                count++;
            }
        }
        
        Integer[] num = new Integer[count];

        if(count > 1){
            for(int i = 0; i<tickets.length; i++){
                if(A[i+1].equals("ICN")){
                    num[i] = i+1;
                }
            }
        }
        
        for(int i = 1; i<tickets.length+1; i++){
            if(A[i].equals("ICN")){
                if(count > 1){
                    B[i] = B[num[i]].charAt(0) > B[num[i-1]].charAt(0) ? B[num[i]] : B[num[i-1]];
                }
                dfs(B[i], tickets, depth);
            }
        }
        
        answer = new String[depth];
        
        for(int i = 0; i<depth; i++){
            answer[i] = stack.pop();
        }
        return answer;
    }
    
    public static void dfs(String begin, String[][] tickets, int depth){
        for(int i = 1; i < tickets.length+1; i++){
            if(A[i].equals(begin) && A[i].equals(B[i-1])){
                stack.add(begin);
                stack.add(B[i-1]);
                dfs(B[i-1], tickets, depth++);
            }
        }
        
    }
}



b. 최종 코드

  • DFS에는 항상 방문배열 추가하기!!

  • 복잡한 로직에서 이것을 List를 이용하여 정렬 이용해서 한 번에 해결하기!

import java.util.*;

class Solution {
    
    static boolean[] visited;
    static List<String> list;
        
    public String[] solution(String[][] tickets) {
        visited = new boolean[tickets.length];
        list = new ArrayList<>();
        
        dfs("ICN", "ICN", tickets, 0);
        Collections.sort(list);
        
        return list.get(0).split(" ");
    }
    
    public static void dfs(String now, String next, String[][] tickets, int depth) {
        if(depth == tickets.length){
            list.add(next);
            return;
        }
        for(int i = 0; i < tickets.length; i++){
            if( !visited[i] && now.equals(tickets[i][0]) ){
                visited[i] = true;
                dfs(tickets[i][1], next + " " + tickets[i][1], tickets, depth+1);
                visited[i] = false;
            }
        }
    }
}



6) 단속카메라

a. 수절하기

  • 테케는 통과하지만, 정확성과 효율성에서 실패! 다시 수정하기!
import java.util.*;

class Solution {
    public int solution(int[][] routes) {
        int answer = 0;
        
        for(int i = 0;  i < routes.length; i++){
            for(int j = i; j < routes.length-1; j++){
                if(routes[j][1] > routes[j+1][0] && routes[j][0] > routes[j+1][0]){
                    answer++;
                }
            }
        }
        return answer;
    }
}



b. 간략히 수정

  • 역시나 테케는 통과하지만, 정확성과 효율성에서 실패! 다시 수정하기!
    • 차량이 1대 이상 10,000대 이하라서 효율성 실패
import java.util.*;

class Solution {
    public int solution(int[][] routes) {
        int answer = 0;
        List<Integer> list = new ArrayList<>();
        
        for(int i = 0;  i < routes.length-1; i++){
            for(int j = i+1; j < routes.length-i; j++){
                if(routes[i][1] < routes[i+j][0]){
                    answer++;
                }
            }
        }
        return answer;
    }
}



c. 최종 수정

  • 이전에 효율성 문제가 발생했기 때문에 for문 2번이 아니라 Collection 등의 자료구조를 이용해야 한다.


  • 정렬을 위해 오름차순을 이용하는 것이 핵심이다.
    • 따라서, 이차원 배열의 정렬을 위해 Comparator 인터페이스를 사용!!


  • 오름차순은 Comparator + 람다식으로 간편하게 사용했다.
import java.util.*;

class Solution {
    public int solution(int[][] routes) {
        int answer = 0;
        
        Arrays.sort(routes, (route1, route2) -> (route1[1] - route2[1]));
        int minNum = Integer.MIN_VALUE;
        
        for(int[] route : routes){
            if(minNum < route[0]){
                minNum = route[1];
                answer++;
            }
        }
        return answer;
    }
}



d. 원래 Comparator 인터페이스 사용

  • 길어서 위처럼 람다식을 이용하여 Comparator를 사용하자!
Arrays.sort(routes, new Comparator<int[]>() {
    @Override
    public int compare(int[] route1, int[] route2) {
        return route1[1] - route2[1];
    }
});



7) 섬 연결하기

a. 수절하기