<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>모현면 실험실</title>
    <link>https://mohyeonman.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 10 Apr 2026 07:53:00 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>모현면</managingEditor>
    <image>
      <title>모현면 실험실</title>
      <url>https://tistory1.daumcdn.net/tistory/5675989/attach/0b6fd5d7e36f4d28975f1b267002b4d6</url>
      <link>https://mohyeonman.tistory.com</link>
    </image>
    <item>
      <title>프로그래머스 LV2 - 다리를 지나는 트럭</title>
      <link>https://mohyeonman.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 프로그래머스에 있는 알고리즘 고득점 Kit 문제들을 풀고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하는 자료구조별로 정리되어있기 때문에, 어떤 식으로 접근해야 하는지 조금이나마 힌트가 되는게 아쉽지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 해당 자료구조보다 더 좋은 방법을 발견하기도 하기 때문에 큰상관은 없는듯 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 스택/큐 로 분류 되는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 카테고리가 &quot;스택/큐&quot;이다보니, 일단은 큐로 시도한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐를 사용하는것 까진 뻔하나,&amp;nbsp; 이 문제의 관건은 &quot;시간&quot; 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 흐르는 것을 어떠한 방식으로 구현할것이냐 의 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 큐를 허수로 가득 채우고, 하나를 꺼낼때마다 시간 +1 하는것으로 구현하기로 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나 poll 한 후, 트럭 또는 허수를 다시 채워넣는것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1740746961071&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        
        Queue&amp;lt;Integer&amp;gt; bridge = new LinkedList&amp;lt;&amp;gt;();
        int nextIndex = 0;
        int currentTime = 0;
        int currentWeight = 0;

		//첫 트럭이 다리를 건너 도착하기 까지의 시간을 구현하기 위해 다리길이 만큼 허수를 넣는다.
        for(int i = 0; i&amp;lt; bridge_length; i++){
            bridge.add(0);
        }

        boolean isValidIndex = true; // 다음 트럭이 있는가?
        while(!bridge.isEmpty()){
            currentWeight -= bridge.poll(); // 트럭을 다리에서 내리고,
            currentTime ++; // 시간이 흐른다.

            if(isValidIndex){
                int nextWeight = truck_weights[nextIndex];
                if(weight &amp;gt;= currentWeight + nextWeight){ // 다음으로 갈 트럭이 있다면,
                    bridge.add(nextWeight); // 트럭이 다리위로 올라가고
                    currentWeight += nextWeight; // 다리 위의 무게가 올라간다.
                    if(truck_weights.length -1 &amp;lt; nextIndex + 1) isValidIndex = false; // 모든 트럭이 올라갔다면 더 시도하지 않도록 한다.
                    else nextIndex++; // 아직 남아있다면 커서를 다음으로 옮긴다.
                }else{
                    bridge.add(0); 
                    // 올라갈 트럭은 아직 남아있으나 무게가 초과된다면
                    // 무게 0의 허수를 넣어 시간의 흐름을 구현한다.
                }
            }
            //더 이상 트럭이 없다면 아무것도 넣지않는다.
            
        }
        return currentTime; // 다리 위가 빈 후 시간을 반환한다.

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이 문제를 보고 가장 먼저 어렴풋 떠오른 방법은, 해시를 사용하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 그래도 출제자의 의도를 맞춰볼까? 하고 풀긴했지만, 해시로도 풀어보고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 해시로 시간의 흐름은 어떻게 구현할것이냐?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while문으로 시간을 계속해서 더하고, 트럭을 다리에 올릴때 (현재시간 +다리의 길이) 만큼을 더해서 저장해둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 해당 시간이 되면, 데이터를 지우고 다리위 무게를 다시 줄여서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 다리에서 내려온 것과 같은 효과를 내도록 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1740747755202&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        
        truckMap = new HashMap&amp;lt;&amp;gt;();

        int currentTime = 0;
        int currentIndex = 0;
        int currentWeight = 0;
        boolean noTrucksLeft = false;

        while(!noTrucksLeft || !truckMap.isEmpty()){ // 올릴 트럭이 없고, map이 빌 때 까지.
            currentTime++;
            currentWeight -= truckMap.getOrDefault(currentTime, 0); // 현재시간에 다리에서 내려와야 하는 트럭의 무게를 뺀다.
            truckMap.remove(currentTime);	//map에서 삭제한다.

            if(!noTrucksLeft){
                int currentTruck = truck_weights[currentIndex];
                if(weight &amp;gt;= currentWeight + currentTruck){
                    truckMap.put(currentTime + bridge_length, currentTruck);
                    currentWeight += currentTruck;

                    if(currentIndex + 1 &amp;gt; truck_weights.length - 1) noTrucksLeft = true;
                    else currentIndex ++;
                }
            }

        }
        
        return currentTime; // 다리 위가 빈 후 시간을 반환한다.

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 이쪽이 훨씬 아름다운 풀이인 듯 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계속해서 데이터를 삽입하는 과정도 없을 뿐더러, 조건문도 덜 복잡해서 이해하기도 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 풀이방법을 제안해주지 않는선에서는, 내 직관을 조금은 믿어봐도 좋을 듯 싶다.&lt;/p&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/25</guid>
      <comments>https://mohyeonman.tistory.com/25#entry25comment</comments>
      <pubDate>Fri, 28 Feb 2025 22:09:14 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV3 - 베스트앨범</title>
      <link>https://mohyeonman.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 3단계치곤 좀 쉬운 축인듯.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장르 별 횟수 합산과, 장르 별 1,2순위의 play의 값들을 저장할 Map을 정의한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장르 별 play들의 순위를 유지하기 위해 우선순위 큐를 활용했으며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;poll로 탈락시키기 위해&amp;nbsp; 우선순위 조건은 반대로 설정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그로 인해 genreCountMap의 반복 순서와&amp;nbsp; poll하여 나열하는 순서를 모두 반대로 진행하였고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막에 역순으로 정렬하여 answer를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든걸 역순으로 진행하는 과정에서 실수가 발생하는걸 막기위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웬만하면 ArrayDeque등을 사용하고 싶었으나 우선순위를 지원하지않기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 구현체를 만들거나 익명클래스를 사용해야 했는데..&lt;br /&gt;그럴 바엔 그냥 꼼꼼하게 잘 확인하면서 그냥 풀기로 했다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740368942457&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    Map&amp;lt;String,Long&amp;gt; genreCountMap; // 장르 별 횟수 합산을 위한 Map
    Map&amp;lt;String,PriorityQueue&amp;lt;Song&amp;gt;&amp;gt; songMap;	// 장르 별 우선순위 큐
    
    public int[] solution(String[] genres, int[] plays) {
        
        genreCountMap = new HashMap&amp;lt;&amp;gt;();
        songMap = new HashMap&amp;lt;&amp;gt;();

        for(int i = 0; i&amp;lt;genres.length; i++){
            String genre = genres[i];
            int play = plays[i];

            genreCountMap.put(genre, genreCountMap.getOrDefault(genre, 0L) + play); // 횟수 합산

            PriorityQueue&amp;lt;Song&amp;gt; songQueue = songMap.computeIfAbsent(genre, k -&amp;gt; new PriorityQueue&amp;lt;&amp;gt;( // count와 id로 우선순위 큐 생성.
                (s1, s2) -&amp;gt; {
                    if (s1.count != s2.count) return Integer.compare(s1.count, s2.count);	// poll로 탈락시키기 위해, 우선순위 반대로 설정.
                    return Integer.compare(s2.id, s1.id);
                }));

            songQueue.add(new Song(i, play));  
            while(songQueue.size() &amp;gt; 2){ // 2개까지만 유지
                songQueue.poll(); // 2개 이후 탈락.
            }
        }

        List&amp;lt;Integer&amp;gt; reversedAnswerList = new ArrayList&amp;lt;&amp;gt;();
        //장르별 plays 합산 역순으로 실행.
        genreCountMap.keySet().stream().sorted(Comparator.comparingLong(genreCountMap::get))
            .forEach(genre -&amp;gt; {
                PriorityQueue&amp;lt;Song&amp;gt; songQueue =  songMap.get(genre);
                while(!songQueue.isEmpty()){ // 역순으로 add
                    reversedAnswerList.add(songQueue.poll().id);
                }
            });
        
        int listSize = reversedAnswerList.size();
        int[] answer = new int[listSize];

		// reversedAnswerList 역순으로 정답 도출
        for(int i = 0; i&amp;lt; answer.length; i ++){
            answer[i] = reversedAnswerList.get(listSize -1 - i);
        }

        return answer;

    }
    

    class Song{
        int id;
        int count;

        public Song(int id, int count){
            this.id = id;
            this.count = count;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;이후 확인해보니 TreeSet 으로 역순 처리 없이도 구현이 가능했다.&lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PriorityQueue 또한 배열을 이용해 Tree 구조를 구현한 것이다 보니, 생각해보면 당연한 사실.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TreeSet은 처음과 끝 노드에 모두 접근이 가능하기 때문에 역순으로 돌릴 필요가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 유의할점은 트리의 구현방식이 달라 TreeSet이 더 많은 메모리를 필요로 한다는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PriorityQueue는 내부적으로 배열을 이용해서 Tree를 구현하기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간선정보 등을 저장하지 않고 자식노드 특정이 가능하지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TreeSet 은 내부적으로 Red-Black Tree를 사용하기 때문에, 각 노드를 인스턴스로 저장하고&lt;br /&gt;인스턴스의 색상(R,B) 과 간선정보(자식노드 참조값) 등을 저장해야 하기 때문이다.&lt;br /&gt;&lt;br /&gt;허허... 다른 방법을 찾았어도 역시나 그냥 역순으로 낫다!&lt;/p&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/24</guid>
      <comments>https://mohyeonman.tistory.com/24#entry24comment</comments>
      <pubDate>Mon, 24 Feb 2025 12:59:39 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV1 - 기사단원의 무기</title>
      <link>https://mohyeonman.tistory.com/23</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제도 아무것도 모르던 시절 시도해봤던 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제의 핵심은 약수들을 찾을때 반복 범위를 최소화 할것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 숫자 x 의 약수들은 반드시 짝을 이루며 인수1 로 숫자를 나누면 인수2를 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 탐색범위를 절반으로 한번 줄일 수 있고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5*5 = 25 와 같이 인수1,2 가 제곱근으로 같은 경우가 있다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후론 이미 구한 값들만 반복될 것이기 때문에 탐색할 이유가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 탐색범위를 숫자 x의 제곱근 까지로 한번 더 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자 x의 제곱근 까지 탐색하며 약수를 찾고, 인수1과 인수2를 한번에 찾는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 중복을 허용하지 않는 Set을 이용해 인수1과 2가 같은경우 ( 제곱근 ) 을 쉽게 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 Set.size()가 limit 보다 커진경우 더 이상 계산은 불필요하기때문에,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;break로 해당 반복문을 즉시 빠져나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740357168355&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
    
class Solution {
    public int solution(int number, int limit, int power) {
        
        int answer = 0;
        
        for (int start = 1; start &amp;lt;= number; start++) { // 모든 number 반복
            Set&amp;lt;Integer&amp;gt; set = new HashSet&amp;lt;&amp;gt;();
            int currentAnswer = 1;
            for (int current = 1; current &amp;lt;= Math.sqrt(start); current++) { // start의 제곱근까지만 계산.
                
                if(start % current == 0){ // 약수인 경우
                    set.add(current);		// 인수1 set에 담기
                    set.add(start / current);	// 인수2 set에 담기
                    currentAnswer = set.size();	// 현재 number의 답 갱신
                }
                
                if(set.size() &amp;gt; limit){		// limit보다 큰 경우
                    currentAnswer = power;	// power로 변경
                    break;		// for 종료.
                }
            }
            answer += currentAnswer;		// 각 number의 해답 합산
        }
        
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금씩 조금씩 착실히 늘고있는 느낌 쏘굿. 느좋.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/23</guid>
      <comments>https://mohyeonman.tistory.com/23#entry23comment</comments>
      <pubDate>Mon, 24 Feb 2025 09:49:16 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV2 - 전화번호 목록</title>
      <link>https://mohyeonman.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제는 프로그래머스 코딩테스트 고득점Kit에 포함된 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 항목으로 추가되어 있으나, 훨씬 간단한 해결방법이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그런지 레벨도 좀 과분하게 책정된 듯 하다.&lt;br /&gt;&lt;span style=&quot;background-color: #263747; color: #b2c0cc; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 전화번호가 다른 전화번호의 접두어로 존재하는 경우가 하나라도 있는지를 판별해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 다른 어떤 설명을 붙히려고해도 그저 &quot;사전 정렬을 이용하면 된다&quot; 라고밖에 설명이 안되는것 같다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 하나의 전화번호가 다른 전화번호의 접두어라면, 바로 다음 인덱스에 해당 전화번호가 올수 밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 1번 인덱스부터 바로&amp;nbsp; i -1 와 비교하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1740355788097&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public boolean solution(String[] phone_book) {
        Arrays.sort(phone_book); // 사전정렬
        
        boolean answer = true; // 기본값 true
        for(int i = 1; i &amp;lt; phone_book.length; i ++){
            if(phone_book[i].startsWith(phone_book[i-1])){ // 바로 전 값이 접두어인지 확인.
                answer = false; // 접두어인 경우 즉시 중단.
                break;
            }
        }
        
        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/22</guid>
      <comments>https://mohyeonman.tistory.com/22#entry22comment</comments>
      <pubDate>Mon, 24 Feb 2025 09:18:08 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV1 - 택배 상자 꺼내기</title>
      <link>https://mohyeonman.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;내가 느끼기에, 프로그래머스의 문제들의 난이도가 같은 단계 내에서도 너무 상이하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0문제같은 1단계도 있는 반면에 2단계같은 1단계도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 나름 1단계가 맞는거같긴 하다만, 깨나 애먹었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 이런식으로 접근했다.&lt;/p&gt;
&lt;pre id=&quot;code_1739797579147&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    public void solution(){

        int n = 13;
        int w = 3;
        int num = 6;

        width = w;

        boolean currentDirection = true;
        int answer = 1;
        int offset = getOffset(num);

        while (true){
            num += w;
            if(currentDirection) num += offset;
            else num -= offset;
            if(n &amp;lt; num) break;

            answer ++;
            currentDirection = !currentDirection;
            
        }

        System.out.println(answer);


    }

    private int getOffset(int num){
        int mod = (num % width);
        int offset = -(width - 1);
        int range = isReversed(num)? width - mod : mod;
        for (int i = 0; i &amp;lt; range; i++) {
            offset +=2;            
        }

        return offset;
    }

    private boolean isReversed(int num){
        return (num / width + 1) % 2 == 0;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스에 따라 offset을 만들어두고, num에서 offset에 따라 값을 보정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작을 정방향으로 보고, 다음층 부터 역방향 정방향을 번갈아가며 offset을 더했다 뺀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히 어떤경우인지를 모르겠으나 일부 테스트에 실패했다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무리 생각해도 더 심플 한 해결방법이 있을것 같다는 생각이 떠나질 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 모든 층을 정방향으로 취급하고, 각 층의 인덱스만 좌우대칭으로 번갈아가며 바꿔보기로 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1739798002475&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void solution(){

    int n = 22;
    int w = 6;
    int num = 8;

    int answer = 0;
    while (num &amp;lt;= n) { // num은 반드시 n보다 커야함.

        int index = (num - 1) % w; // 현재 num의 인덱스
        int diff = w - 1 - index; // 대칭이 되는 위치

        num += 2 * diff + 1; // 대칭이 되는 위치로 이동.
        answer ++;
    }
    System.out.println(answer);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말도안되게 간단해졌다. 현재 인덱스를 기준으로 좌우대칭인 인덱스를 찾고, 그 인덱스까지 갈 수 있는 값을 계산한다.&lt;br /&gt;이리하여 훨씬 간단하게 마무리 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번에 떠올려내진 못했지만, 시행착오를 거쳐 작은 단계의 해결부터 찾았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 그 작은 단계를 통해 점화식을 완성하는데 성공했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직관으로 볼땐 복잡했던 문제를, 분석을 통해 간단히 도식화 하는게 참... 이 맛이 알고리즘 맛이 아닐까?&lt;/p&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/21</guid>
      <comments>https://mohyeonman.tistory.com/21#entry21comment</comments>
      <pubDate>Mon, 17 Feb 2025 22:22:16 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV1 - 달리기 경주</title>
      <link>https://mohyeonman.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;정말 아무것도 모르던 시절. 이미 한번 도전했던 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;players의 범위도 5&amp;lt;= players &amp;lt;= 50,000 인데다,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;callings의 범위도 2&amp;lt;=callings &amp;lt;= 1,000,000 이기 때문에, 아마도 타임아웃에 부딪혔을 수도 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 땐 그래도 조금이나마 늘긴 늘었단 생각이 든다. 작성시간까지 해서 10분 정도 걸렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참 아직도 갈 길이 멀다만 그때의 나는 뭐였을까..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 문제로 돌아가서, 이 문제의 관건은 callings의 값으로 어떻게 플레이어를 빠르게 찾느냐 다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 배열과 해시로 동시에 관리하기로 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순위가 바뀔때, 배열과 해시를 동시에 갱신해주면, 선수 이름으로 현재 순위를 바로 가져올 수 있고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 순위로 배열에 다시 접근 하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739370477435&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    private Map&amp;lt;String,Integer&amp;gt; currentRankMap;

    public String[] solution(String[] players, String[] callings) {

        init(players);

        for (String call : callings) {
            int currentRank = currentRankMap.get(call);
            String passed = players[currentRank - 1]; //지나친 선수

            players[currentRank] = passed; // 배열에서 순위 교체
            players[currentRank - 1] = call;

            currentRankMap.put(passed, currentRank); // 해시에서 순위 갱신
            currentRankMap.put(call, currentRank - 1);
        }

        return players;
    }

	// 초기화
    private void init(String[] players){

        currentRankMap = new HashMap&amp;lt;&amp;gt;();

        for (int i = 0; i &amp;lt; players.length; i++) {
            String player = players[i];
            currentRankMap.put(player, i);
        }

    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/20</guid>
      <comments>https://mohyeonman.tistory.com/20#entry20comment</comments>
      <pubDate>Wed, 12 Feb 2025 23:29:34 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV1 - 공원 산책</title>
      <link>https://mohyeonman.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 커다란 함정이 숨어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그것은 그리드에서 (0,0)의 좌표가 왼쪽 위고, (h-1,w-1) 이 왼쪽 아래라는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 위아래 뒤집어서 생각하고, South 또는 North로 이동할때 Y 값을 반대로 적용해주면 특별히 신경쓸 일이 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좌표평면 위를 이동하는 문제에서 0,0의 위치도 당연시 하면 안된다는 경각심을 주는 문제인것도 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 그걸 제외하면 어려운 문제는 확실히 아니었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 풀고나서 아차 싶었던 점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 무의식적으로 재귀함수로 풀었는데, 만약 이동거리의 범위가 &quot;1&amp;lt;=n&amp;lt;= 10&quot; 이 아니었다면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 park의 크기가 엄청나게 컸다면 재귀함수 깊이문제가 발생했을 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제한사항을 보고 다시보자....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739367816338&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    private int w,h;
    private int[] start;
    private Map&amp;lt;String,int[]&amp;gt; offsetMap;
    private boolean[][] isWall;

    public int[] solution(String[] park, String[] routes) {
        init(park);

        for (String route : routes) {
            String[] s = route.split(&quot; &quot;);
            String d = s[0];
            int r = Integer.parseInt(s[1]);
            int[] offset = offsetMap.get(d);
            boolean isPossible = recursive(offset, start[0], start[1], r);

            if(isPossible){
                for (int i = 0; i &amp;lt; r; i++) {
                    start[0] += offset[0];
                    start[1] += offset[1];
                }
            }


        }
        return start;


    }


    private void init(String[] park){

        h = park.length;
        w = park[0].length();

        offsetMap = new HashMap&amp;lt;&amp;gt;();
        isWall = new boolean[h][w];

        offsetMap.put(&quot;E&quot;, new int[]{0,1});
        offsetMap.put(&quot;W&quot;, new int[]{0,-1});
        offsetMap.put(&quot;N&quot;, new int[]{-1,0}); //상하 반대로되어있음.
        offsetMap.put(&quot;S&quot;, new int[]{1,0});

        for (int i = 0; i &amp;lt; h; i++) {
            String string = park[i];
            for (int j = 0; j &amp;lt; w; j++) {
                char al = string.charAt(j);
                if(al == 'O' || al == 'S'){
                    if(al == 'S'){
                        start = new int[]{i,j};
                    }
                    isWall[i][j] = false; 
                    continue;
                }
                isWall[i][j] = true;
            }
        }

    }

    private boolean isValid(int y, int x){
        if(y &amp;gt; h - 1 || x &amp;gt; w -1 || y &amp;lt; 0 || x &amp;lt; 0) return false;
        return true;
    }

    private boolean recursive(int[] offset, int curY, int curX, int count){
        if(!isValid(curY, curX) || isWall[curY][curX]) return false;
        if(count == 0 ) return true;
        return recursive(offset, curY + offset[0], curX + offset[1], count - 1);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/19</guid>
      <comments>https://mohyeonman.tistory.com/19#entry19comment</comments>
      <pubDate>Wed, 12 Feb 2025 22:50:30 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV1 - 대충 만든 자판</title>
      <link>https://mohyeonman.tistory.com/18</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 그냥 아무 문제나 잡아서 풀어봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 여지껏 내 수준보다 어려운 문제 위주로 풀어왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어찌어찌 방법을 찾고 답을 구하긴 했지만, 기준된 시간을 한참 넘어서는 경우도 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 온탕 냉탕을 오가듯 낮고 높은 난도를 골고루 풀어야겠다고 느낀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다보면 점점 늘겠지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 1단계라곤 해도, 문제를 보는 순간 답이 나오고 5분안에 작성까지 끝난 것이,&lt;br /&gt;썩 기분이가 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739280371768&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    private Map&amp;lt;Character,Integer&amp;gt; keyMinMap = new HashMap&amp;lt;&amp;gt;();
    private int keyMax = 100;

    public int[] solution(String[] keymap, String[] targets) {

        for (String keys : keymap) {
            for (int i = 0; i &amp;lt; keys.length(); i++) {
                char key= keys.charAt(i);
                int currentMin = keyMinMap.getOrDefault(key, keyMax);
                keyMinMap.put(key, Math.min(currentMin, i + 1));
            }
        }

        int[] answer = new int[targets.length];
        for (int i = 0; i &amp;lt; targets.length; i++) {
            String string = targets[i];
            int sum = 0;
            for (int j = 0; j &amp;lt; string.length(); j++) {
                char key = string.charAt(j);
                if(!keyMinMap.containsKey(key)) {
                    sum = -1;
                    break;
                }
                sum += keyMinMap.get(key);
            }
            answer[i] = sum;
        }

        return answer;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/18</guid>
      <comments>https://mohyeonman.tistory.com/18#entry18comment</comments>
      <pubDate>Tue, 11 Feb 2025 22:31:45 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV2 - 지게차와 크레인</title>
      <link>https://mohyeonman.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;좌표들을 문자열별로 모아두고 처리하는 것까진 쉽게 생각이 닿았지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나씩 빼내는 과정에서 새로운 가장자리들을 정의하는 것은 쉽지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 단순히 빼내는 상자 주변에 대해서만 고려했는데, 한번 틀리고나니 아차싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 상자가 빠짐으로써, 상자들에 감싸져있던 빈공간이 댐처럼 터져&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 밖에서 접근가능한 가장자리가 될 수 있다는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 상자가 빠지는 동시에 주변의 빈공간을 타고 BFS로 퍼져나가,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 가장자리가 될 여지가 있는 상자들을 찾는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 퍼져나가며 !isValid가 되는지 확인하고, ( 인덱스 범위를 벗어남으로 외부에서 접근가능한 것으로 간주한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장자리를 재정의한다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 내부로직을 짜는데 생각보다 많은시간이 걸렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;offset 반복문 이전, 이후에 각각 어떤처리를 해야하는지 너무 헷갈렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 반복문 내부에서 다 처리했기 때문에.. 쓸모없는 반복은 조금 더 생겼을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한&amp;nbsp; isEdge()등을 활용해서 백트래킹도 가능할 것 같지만.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;효율성 검사도 없을 뿐더러 내 수준에 이정도면 충분하다. so 충분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739251838571&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.util.stream.Collectors;

class Solution {
    
    Map&amp;lt;Character, List&amp;lt;int[]&amp;gt;&amp;gt; coordiMap;
    int n,m;
    boolean[][] boundary ;
    boolean[][] removed ;
    int[] offsetX = {-1, 0, 1, 0};
    int[] offsetY = {0, -1, 0, 1};
    
    public int solution(String[] storage, String[] requests) {
        // 초기화
        coordiMap = new HashMap&amp;lt;&amp;gt;();
        n = storage.length;
        m = storage[0].length();
        boundary = new boolean[n][m];
        removed = new boolean[n][m];

        int answer = n * m;

        //map에 알파벳 별로 모으기
        for (int i = 0; i &amp;lt; n; i++) {
            for (int j = 0; j &amp;lt; m; j++) {
                char al = storage[i].charAt(j);
                List&amp;lt;int[]&amp;gt; coordiList = coordiMap.computeIfAbsent(al, k -&amp;gt; new ArrayList&amp;lt;&amp;gt;());
                coordiList.add(new int[]{i,j});
                if(isEdge(i,j)) boundary[i][j] = true;
            }
        }

        //요청 순차적으로 실행
        for (String request : requests) {
            char[] chars = request.toCharArray();
            boolean isCrain = chars.length &amp;gt; 1; // &quot;A&quot; or &quot;AA&quot;

            char al = chars[0];
            
            List&amp;lt;int[]&amp;gt; coordiList = coordiMap.getOrDefault(al, Collections.emptyList()); //해당 알파벳 전체.
            List&amp;lt;int[]&amp;gt; targetList;
            if(isCrain){
                targetList = coordiList; 
                coordiMap.remove(al); // 해당 알파벳 삭제
            }else{
                targetList = coordiList.stream().filter(coordi -&amp;gt; {
                    int x = coordi[0];
                    int y = coordi[1];
                    return !removed[x][y] &amp;amp;&amp;amp; boundary[x][y]; // 지워지지 않았고, 가장자리에 있는것 특정
                }).collect(Collectors.toList());
                coordiList.removeAll(targetList);
                coordiMap.put(al, coordiList); // targetList뺀 나머지로 갱신
            }

            targetList.forEach(coordi -&amp;gt; outBfs(coordi)); //bfs 실행.

            answer -= targetList.size();

        }

        

        return answer;
    }
    
    
    private boolean isEdge(int x, int y) {
        return (x == 0 || x == n-1 || y == 0 || y == m-1);
    }

    private boolean isValid(int x, int y) {
        return (0 &amp;lt;= x &amp;amp;&amp;amp; x &amp;lt; n &amp;amp;&amp;amp; 0 &amp;lt;= y &amp;amp;&amp;amp; y &amp;lt; m);
    }

    private void outBfs(int[] coordi){
        int x = coordi[0];
        int y = coordi[1];

        //일단 removed에서 삭제처리.
        removed[x][y] = true;

        Queue&amp;lt;int[]&amp;gt; bfsQueue = new LinkedList&amp;lt;&amp;gt;(); // bfs 큐
        List&amp;lt;int[]&amp;gt; targetNodes = new ArrayList&amp;lt;&amp;gt;(); // 새로운 가장자리가 될 노드들.
        boolean[][] visited = new boolean[n][m]; // 방문 기록
        boolean isOpened = false; //외부와 연결 여부.

        bfsQueue.add(coordi);
        
        while (!bfsQueue.isEmpty()) {
            int[] cur = bfsQueue.poll();
            int cx = cur[0];
            int cy = cur[1];

            for (int o = 0; o &amp;lt; 4; o++) {
                int nx = cx + offsetX[o];
                int ny = cy + offsetY[o];

                if(!isValid(nx, ny)){
                    isOpened = true;
                    continue;
                }
                if(visited[nx][ny]) continue;
                
                if(!removed[nx][ny]){
                    if(!boundary[nx][ny]){
                        targetNodes.add(new int[]{nx,ny}); // 삭제X, 가장자리x 새로운 가장자리 예정.
                    }
                }else{
                    bfsQueue.add(new int[]{nx,ny}); // 삭제O 데이터들만 queue로 추가.
                }

                visited[nx][ny] = true;

            }

        }

        if(isOpened) { // 삭제된 데이터를 타고간 결과 !isValid에 도달한 경우.
            for (int[] node : targetNodes) {
                boundary[node[0]][node[1]] = true; // 새로운 가장자리로 결정
            }
        }
        
    }

}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/17</guid>
      <comments>https://mohyeonman.tistory.com/17#entry17comment</comments>
      <pubDate>Tue, 11 Feb 2025 21:59:11 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 LV2 - 충돌위험 찾기</title>
      <link>https://mohyeonman.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;하.. 정말 고전했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 읽음과 동시에 해법이 얼추 그려졌음에도 불구하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IOB가 어디서 발생하는지 찾느라 아주 애먹었다....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나하나 차근히 살펴볼 필요가 있겠다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739191776783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

class Solution {
    public int solution(int[][] points, int[][] routes) {
        List&amp;lt;Robot&amp;gt; robots = new ArrayList&amp;lt;&amp;gt;();
        for (int i = 0; i &amp;lt; routes.length; i++) {
            int robotId = i;
            int currentPointIndex = routes[i][0] - 1;
            robots.add(new Robot(robotId, Arrays.copyOf(points[currentPointIndex],2)));
        }

        int answer = 0;

        while(!robots.stream().allMatch(r -&amp;gt; r.arrived)){

            Map&amp;lt;String,Integer&amp;gt; siteMap = new HashMap&amp;lt;&amp;gt;();
            for (Robot robot : robots) {
                if(!robot.arrived){
                    int robotId = robot.robotId;
                    int stopIndex = robot.stopIndex;
                    int pointIndex = routes[robotId][stopIndex] - 1;
                    int[] goal = points[pointIndex];
                    robot.move(goal);
                    if(robot.current[0] == goal[0] &amp;amp;&amp;amp; robot.current[1] == goal[1]){
                        if(stopIndex + 1 &amp;lt; routes[robotId].length) robot.stopIndex += 1;
                        else robot.arrived = true;
                    }

                    String currentSiteKey = Arrays.toString(robot.current);

                    int currentSiteCount = siteMap.getOrDefault(currentSiteKey, 0);
                    siteMap.put(currentSiteKey, currentSiteCount + 1);
                }

            }
            answer += siteMap.values().stream().filter(v -&amp;gt; v &amp;gt; 1 ).count();

        }

        return answer;

    }

    class Robot{
        int robotId;
        int stopIndex = 0;
        int[] current;
        boolean arrived;

        public Robot(int robotId, int[] current){
            this.robotId = robotId;
            this.current = current;
        }

        public void move(int[] goal) {
            if (current[0] != goal[0]) {
                if (goal[0] - current[0] &amp;gt; 0) current[0] += 1;
                else current[0] -= 1;
            } else if (current[1] != goal[1]) {
                if (goal[1] - current[1] &amp;gt; 0) current[1] += 1;
                else current[1] -= 1;
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while문 조건을 좀더 예쁘게 처리할 수 있을 것 같지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타임아웃에 문제는 없을 것 같아 그냥 그대로 뒀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계획을 좀더 철저히 세워서 접근하는 습관을 들여야할 듯 싶다.&lt;/p&gt;</description>
      <category>STUDY/ALGORITHM</category>
      <author>모현면</author>
      <guid isPermaLink="true">https://mohyeonman.tistory.com/16</guid>
      <comments>https://mohyeonman.tistory.com/16#entry16comment</comments>
      <pubDate>Mon, 10 Feb 2025 21:51:52 +0900</pubDate>
    </item>
  </channel>
</rss>