SSAFY 1학기를 비전공 파이썬으로 마치고 나면 파이썬으로 알고리즘을 풀이하는 것에 익숙해지게 됩니다.

 

하지만, 요즘 기업에서 파이썬이 아닌 자바로만 코딩테스트를 보는 기업들이 점점 늘어나고 있어,

 

파이썬으로만 알고리즘 문제를 풀었던 친구들이 코딩테스트 때문에 입사지원을 포기하게 되는 경우를 종종 보게 됩니다.

 

하지만, 파이썬으로 알고리즘 문제를 풀 수 있다면, 로직을 짤 수 있는 사고 및 추론 능력은 충분합니다.

 

자바로 해당 코드를 어떻게 짜야하는가만 알면 금세 자바로 코딩테스트를 통과할 수 있을겁니다.

 

제가 느꼈던 "파이썬으로는 이렇게 풀면 되는데 자바로는 어떻게 코드를 짜야하지?" 의 생각들을 

 

정리해둔다면 다른 비전공자 학생들도 자바로 코딩테스트를 무난하게 풀 수 있을 것이라 생각하여 글을 작성하게 되었습니다.

 

파이썬과 자바의 가장 큰 차이는 정적언어와 동적언어의 차이일겁니다.

 

lst = [] 으로 리스트를 간단하게 만들 수 있고

 

lst.append("1")

lst.append(1) 

 

이렇게 다양한 타입의 언어들을 하나의 리스트에 다 넣어도 문제가 생기지 않는 파이썬에 익숙해지다보면

 

다양한 타입들을 리스트에 넣어야 하는 상황을 맞닥뜨리게 될 때 당황하게 됩니다.

 

배열보단 동적으로 가변 메모리를 갖는 리스트에 익숙하다보니 가변길이를 갖는 리스트를 찾게되고,

 

List<Integer> lst = new ArrayList<>(); 이렇게 만들면 간단하게 파이썬의 list와 비슷한 구현이 가능하겠구나! 라고 생각한 사람들에게 첫번째 관문이 바로 타입입니다.

 

문제로 예시를 들어보도록 하겠습니다.

 

https://school.programmers.co.kr/learn/courses/30/lessons/1844

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

전형적인 bfs문제이며, row, column, depth를 체크해주면 되는 문제입니다.

 

Queue<int[]> q = new LinkedList<>(); 를 사용하여 Queue를 만든 뒤, [r, c, d] 형태로 넣어도 되겠지만,

 

만약 d가 숫자가 아니라 문자열이라면 int[]에 담을 수 없게 되기에 난관에 봉착하게 됩니다.

 

그렇기에 타입을 여러개 담을 수 있는 Class에 익숙해져야 합니다.

 

class Solution {
    
    public static class Player{
        
        int row;
        
        int column;
        
        int depth;
        
        public Square(){
        }

        
    }
    public int solution(int[][] maps) {
       
        int answer = 0;
        
        Player player = new Player();
        
        
        
        return answer;
    }
}

 

Player 객체를 만들고, 해당 플레이어의 row, column, 그리고 몇 번 움직여서 들어갔는지 체크할 depth 변수를 갖게 해줍니다

 

 public int bfs(Queue<Player> q, int[][] maps){
        
        boolean[][] visited = new boolean[endRow][endColumn];
        
        visited[0][0] = true;
        
        while(true){
            if(q.isEmpty()){
                return -1;
            }
            Player player = q.poll();
            
        if(player.row == endRow-1 && player.column == endColumn-1){
            return player.depth+1;
        }
            
        for(int d = 0; d<4; d++){
            int nr = player.row + dr[d];
            
            int nc = player.column + dc[d];
            
            if(isValid(nr, nc) && maps[nr][nc] == 1 && !visited[nr][nc]){
                q.add(new Player(nr, nc, player.depth+1));
                
                visited[nr][nc] = true;
            }
        }
        }
        
        
    }

 

bfs의 로직을 보면 Player 객체를 만들어 그 안의 값들을 조작할 수 있습니다.

 

이렇게 파이썬에서 list안에 담던 것들을 객체로 만들어주면 좀 더 직관적으로 자바를 이용한 코딩테스트를 치룰 수 있습니다.

 

이중리스트의 경우에도 대부분은 내부 리스트가 아닌 객체 하나로 처리할 수가 있습니다.

 

객체지향적으로 코딩테스트를 풀을 필요는 없지만, 각각의 문제에 나온 요소들을 객체로 만들어서 관리해주면 좀 더 문제를 풀기에 편해진다는 걸 생각하면 

 

파이썬에서 자바로 코딩테스트 언어를 옮기는 것은 그렇게 어렵지 않습니다

자바로 처음으로 이분탐색을 구현해보았는데, 파이썬이랑 사실상 다를게 없어서 가볍게 구현할 수 있는 문제.

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AXNQOb3avD0DFAXS 

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

인덱스를 선택하고 거기서 오른쪽으로 최장 몇칸 갈 수 있는지를 체크한다.

 

왼쪽은 고려하지 않아도 되는게, 왼쪽 인덱스에 바로 붙어있어 연속되는 수강일이 있다고 하더라도, 이미 왼쪽에서 처리해주면서 넘어왔기 때문에 왼쪽은 볼 필요가 없다.

 

1. 반복문으로 모든 수강일를 돌기

 

2. 오른쪽 인덱스로 하나 늘어날 때마다 수강한 날이 하나 늘어남

 

3. 오른쪽 인덱스 - 선택한 인덱스 + 1 = 수강한 날의 일 수, 오른쪽 값 - 선택한 값 + 1 = 전체 일 수

 

4. 전체 일 수 - 수강한 날 수 = 해킹해서 채워야 하는 날 수

 

5. 정답의 최솟값은 각각의 수강 날짜가 너무 범위가 커서 수강 날짜를 이을 수 없어, 하나의 날짜에 p로 덧붙이는 경우

ex) 4 420 (수강한 날은 2일이지만, 전체 일수는 417일, 그러므로 하나만 고르고 p로 이어붙이는 1+p가 최솟값)

 

6. 오른쪽 인덱스를 정하고 나면 해당 인덱스까지 연속으로 잇기 위해 필요한 날짜만큼 p에서 빼고, 남은 p값은 추가로 더해주기 == 해당 기간동안 수강한 날수 + p

 

import java.util.*;
import java.io.*;
public class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        for(int t = 1; t<= T; t++){
            int n = sc.nextInt();
            int p = sc.nextInt();
            int[] lst = new int[n];
            for(int i=0; i<n; i++){
                lst[i] = sc.nextInt();
            }
            int answer = 1 + p;
            for(int i=0; i<n-1; i++){
                int start = i+1;
                int end = n-1;
                int res = i;


                while(start <= end){
                    int mid = (start + end)/2;
                    int totalDay = lst[mid] - lst[i] + 1;
                    int attendDay = mid - i + 1;
                    if(totalDay - attendDay <= p){
                        start = mid + 1;
                        res = mid;
                    }else{
                        end = mid - 1;
                    }
                }
                int totalDay = lst[res] - lst[i] + 1;
                int attendDay = res - i + 1;
                answer = Math.max(answer, p - (totalDay - attendDay) + totalDay);

            }
            System.out.println("#"+t+" "+answer);
        }

    }
}

 

2의 100 제곱을 간단하게 구현하려면 어떻게 해야할까요?

 

 

int N = 1;

for(int i=0; i<100; i++){
    N *= 2;

}

이렇게 하면 2의 100제곱을 구할 수 있겠습니다.

 

하지만 100번의 연산을 하는 것은 매우 비효율적입니다.

 

2의 제곱인 4를 구했다면, 4의 제곱인 16을 빠르게 알 수 잇고, 16의제곱인 196도 빠르게 알 수 있고,

 

이렇게 기존에 구해놓은 값을 이용하면 훨씬 효율적으로 제곱값을 구할 수 있겠습니다.

 

만약 제곱을 알고 있다면 이런식으로 값을 알아내는게 가능해질겁니다.

 

 

2의 100제곱은 2의제곱의 50제곱입니다.

 

2의제곱은 4죠.

 

4의 50제곱은 4의 제곱의 25제곱입니다.

 

4의제곱은 16이고, 4의제곱의 25제곱은 4의제곱의 24제곱 * 4의제곱입니다. 

 

홀수일경우, 제곱으로 뽑아낼 수가 없으므로 제곱으로 뽑아내기 전에 해당 제곱수를 나중에 곱해주기 위해 저장해둡니다.

 

이런식으로 반복하면 마지막 1이 됐을 때, 만들어진 제곱수에 홀수제곱 때 저장해두었던 값들을 모두 곱해주면 2의100제곱을 만들 수 있습니다.

 

코드로 보시죠.

 

import java.util.*;
import java.io.*;
public class Solution{

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int pow = sc.nextInt();
        int ans = 1;
        while(pow > 0){
            if(pow % 2 == 1){
                //홀수일 경우 제곱으로 뽑아낼 수 없으므로 하나를 빼두고 나중에 곱해줄 것
                ans *= num;
                if(pow == 1){
                    break;
                }
            }
            //제곱수로 뽑아내기
            num *= num; // 2의 pow제곱은 2의 제곱의
            pow /= 2; // pow/2 제곱
        }
    System.out.println(ans);
    }
}

홀수인지 확인해서 홀수라면 제곱수로 못 뽑아내니 하나는 미리 곱해주고, 나머지를 제곱수로 뽑고, 제곱해야할 pow값은 반으로 줄여주고,

 

이렇게 반복하다보면 1일때 마지막으로 ans에 마지막으로 구한 값이 곱해질거고, 그게 구하고싶은 제곱의 값이 될겁니다.

 

 

 

7. add 구현하기

이제 addFirst와 addLast가 아닌 특정 인덱스에 data를 삽입하는 add를 구현해보도록 하겠습니다.

 

우리는 이제 get을 통하여 특정 인덱스의 Node에 접근을 할 수 있었습니다.

 

그럼 add를 구현하기 아주 쉬워지는데요.

 

0번째 인덱스에 데이터를 삽입하는 경우는 addFirst와 같으니 addFirst를 써주고

 

그 외의 인덱스에 추가하는 것은 해당 인덱스와 그 이전의 인덱스 사이에 노드를 넣어주는 것이기 때문에

 

그 두개를 받고 next를 이어주기만 하면 됩니다.

 

public void add(int index, int data){
            if(index==0){
                addFrist(data);
            }else{
                Node newNode = new Node(data);
                Node prev = get(index-1);
                Node next = get(index);
                prev.next = newNode;
                newNode.next = next;
                size++;
                }
}

 

이런 느낌이죠. index가 0이라면 addFirst를 해주면 되고, 그 이외에는 새로운 노드를 만들어서 데이터를 넣어준뒤

 

이전 인덱스와 해당 인덱스의 노드를 받아서 next로 이어주면 끝

 

그런데, addFirst와 addLast를 구현할 때 중요한게 head값과 tail값이었잖아요?

 

인덱스가 0일때는 addFirst를 호출하니 상관 없는데, 마침 해당 인덱스가 마지막 인덱스였다면 tail값을 수정해주는 작업이 필요합니다.

 

간단하게 newNode의 next가 null이라면 tail을 newNode로 바꿔주면 됩니다.

 

 

public void add(int index, int data){
            if(index==0){
                addFrist(data);
            }else{
                Node newNode = new Node(data);
                Node prev = get(index-1);
                Node next = get(index);
                prev.next = newNode;
                newNode.next = next;
                size++;
                if(newNode.next == null){
                    this.tail = newNode;
                }
            }

        }

 

8. removeFirst 구현하기

 

removeFirst는 매우 간단합니다.

 

LinkedList의 head값을 head.next 값으로 바꿔주기만 하면 되니까요

public int removeFirst(){
            Node node = this.head;
            this.head = head.next;
            size--;
            return node.data;
        }

매우 쉽습니다.

 

9. remove 구현하기

 

그럼 이제 특정 인덱스의 값을 remove하는 것을 알아보도록 하겠습니다.

 

add와 크게 다르지 않습니다. 만약 첫번째 인덱스를 remove한다면 removeFirst를 실행해주고,

 

그게 아니라면 해당 인덱스의 이전 인덱스 노드와 다음 인덱스 노드를 받아서 그 두개를 다시 이어주면 되니까요.

 

하지만, add를 할 때와 마찬가지로 우리가 삭제하려는 값이 마지막 인덱스라면 tail;값의 변경이 필요하게 될겁니다.

 

public int remove(int index){
            if(index==0){
                return removeFirst();
            }else{
                Node selectedNode = get(index);
                Node prev = get(index-1);
                Node nextNode = prev.next.next;
                prev.next = nextNode;
                if(selectedNode == tail){
                    this.tail = prev;
                }
                size--;
                return selectedNode.data;
            }
        }

 

10. removeLast 구현하기

 

removeLast remove에 size-1을 실행하면 됩니다.

 

SSAFY B형 특강을 듣다가 처음으로 알게 된 Linked LIst

 

파이썬으로도 구현이 가능하다고 하는데, 비전공자반 수업시간에서 다루지 않았던 자료구조이기도 하고,

 

JAVA를 다루는데 아직 익숙하지 않아서인지 간단해 보이면서도 구현하기가 쉽지 않아 정리를 해두려고 합니다.

 

1. Linked List 만들기

 

Linked List는 노드들로 이루어져있는데요

 

원소 하나하나가 노드로 이루어져 있는 리스트라고 생각하면 될 것 같습니다.

 

맨 앞과 맨 뒤의 노드는 은근히 쓰일 일이 많기 때문에 Linked List 자체적으로 가지고 있도록 만들어 놓습니다.

 

그리고 size나 empty를 쉽게 구현하기 위해 size 값도 멤버변수로 하나 넣어놓습니다.

public class TestLinkedList{

    public static class LinkedList{
        Node head;
        Node tail;
        int size;
        public LinkedList(){
            this.head = null;
            this.tail = null;
            this.size=0;
        }
    }
}

 

2. Node 만들기

 

어차피 노드들은 이 Linked List 안에서만 사용될 것이기 때문에 클래스 안에 Node 클래스를 추가로 만듭니다.

 

각 Node들은 data를 갖고, next라는 레퍼런스 변수를 이용하여 다음 노드를 참조합니다.

 

값이 없는 노드는 없으므로 노드는 노드를 생성할 때 생성자로 받아주고, next 값은 링크드리스트에 연결을 해주어야 하니 일단 null으로 설정해준 뒤 직접 이어줄겁니다.

public class TestLinkedList{

    public static class LinkedList{
        Node head;
        Node tail;
        int size;
        public LinkedList(){
            this.head = null;
            this.tail = null;
            this.size=0;
        }
        // 추가되는 부분
        public class Node{
            int data;
            Node next;
            public Node(int data){
                this.data = data;
                this.next = null;
            }
        }
        //Node 완성
    }
}

 

3. addFirst 만들기

맨 앞에 원소를 추가하는 메소드입니다.

 

원소를 추가할 때 해줘야할 건 총 3가지입니다.

 

 -  head값 바꾸기

일단 새로운 노드를 맨 앞에 위치시킬 것이기 때문에, head값을 바꿔주어야 합니다.

 

일단 새로 만든 노드에 기존의 head를 연결시켜놓고 head를 바꿔주면 됩니다.

 

- size증가시키기

당연합니다.

 

 - 기존의 head가 null인지 체크하기

 이제 새로운 노드가 head가 되었습니다. head.next를 체크해줍니다. 만약 head.next가 null이라면 기존에 아무 노드도 없었다는 뜻이 됩니다. 이제 첫번 째 노드가 생겼으니 null이었던 head와 tail값을 모두 지정해줍니다. head == tail == newNode인 상태겠죠.

 

public class TestLinkedList{

    public static class LinkedList{
        Node head;
        Node tail;
        int size;
        public LinkedList(){
            this.head = null;
            this.tail = null;
            this.size=0;
        }
        public class Node{
            int data;
            Node next;
            public Node(int data){
                this.data = data;
                this.next = null;
            }
        }

        public void addFrist(int data){
            // 노드를 생성하고
            Node newNode = new Node(data);
            // 기존에 있던 head에 연결을 해줍니다.
            newNode.next = head;
            // 그리고 생성한 노드가 이제부터 head가 됩니다.
            head = newNode;
            // 만약 현재 헤드의 next가 없다면 노드가 하나뿐이므로 tail값 역시 현재 노드가 됩니다.
            if(head.next == null){
                tail = head;
            }
            size++;
        }
    }
}

 

4. addLast 만들기

 

 이번엔 처음이 아닌 마지막에 Node를 추가합니다. 당연히 newNode가 tail이 되겠죠?

addFirst와 크게 다르지 않습니다.

public void addLast(int data){
            Node newNode = new Node(data);
            tail.next = newNode;
            tail = newNode;
            size++;
        }

간단하게 이렇게 짜면 될까요?

 

이렇게 짜면 되긴 합니다만, tail값이 null일 경우를 생각하지 않았습니다.

 

tail값이 null이라면 작동하지 않습니다. 그렇기 때문에 tail이 null일 경우, 즉 리스트가 비어있을 경우에 필요한 로직을 짜주어야 합니다.

 

그 로직은 이미 addFirst에서 우리가 만들어두었습니다.

 public void addLast(int data){
            Node newNode = new Node(data);
            if(size == 0){
                addFrist(data);
            }
            tail.next = newNode;
            tail = newNode;
            size++;
        }

 

5. toString으로 확인하기

 

 이제 로직이 잘 확인하는지 테스트하기 위해 toString 함수를 만듭니다.

head부터 next로 이동하면서 data값들을 출력해주면 될 것 같습니다.

 

toString 함수는 간단하게 이렇게 작성하면 될 것 같아서 작성을 해보았는데

 

이렇게 작성하니까 값이 비어있을 때 에러가 나더라구요.

 

size값을 넣어서 size가 0이면 [] 만 출력하게 해놓는게 더 좋을 것 같습니다.

 

public String toString(){
            Node start = this.head;
            String str = "[" + this.head.data;
            while(start.next != null){
                start = start.next;
                str += "," + start.data;
            }
            str +=  "]";
            return str;
        }
 public static void main(String[] args) {
        LinkedList lst = new LinkedList();
        lst.addFrist(1);
        lst.addFrist(2);
        lst.addLast(3);
        lst.addFrist(4);
        System.out.println(lst);
    }

결과가 제대로 출력이 되는 걸 볼 수 있습니다.

 

1 -> 2, 1 -> 2, 1, 3 -> 4, 2, 1, 3 

 

6. index로 접근하기

LinkedList는 인덱스로 바로 접근할 수가 없습니다. 그렇기 때문에 순차적으로 접근해서 값을 얻어내야하는데요

public Node get(int index){
            Node node = this.head;
            for(int i=0; i<index; i++){
                node = node.next;
            }
            return node;
        }

이렇게 하면 간단하게 인덱스에 해당하는 node를 얻을 수 있겠죠?

 

이렇게 LinkedList로 맨 앞과 맨뒤에 값을 추가하고, 인덱스로 접근하는 방법을 알아보았습니다. 

 

다음에는 중간에 삽입하는 방법과 삭제한느 방법을 익혀보도록 하겠습니다.

 

 

 

장담하는데 파이썬으로 풀었다면 30분도 안걸려서 풀 수 있는 정말 간단한 문제였을 것 같다.
 
분명 로직은 정말 쉬운데... 자바로 구현하는게 너무 어렵다
 
자바로 알고리즘 푸는게 정말 맞는걸까 싶어지지만, 자바로 나중에 비즈니스 로직을 짜게 될 때, 자바로는 할 줄 몰라요 라고 말할 수는 없으니깐!!!
 
정말... 이 문제를 풀면서 30번 정도는 생각한 것 같다
 
이렇게 푸는게 맞나...? 정말 이렇게 푸는게 맞나? 이렇게 구현하는게 맞나..? 자바로 알고리즘 푸는 사람들 다 이렇게 구현했을까...?
 
그래서 일단 어거지로 풀고, 다른 사람들 코드 보기를 열어서 봐야겠다는 마음으로 어거지로 풀어버렸다.
 
근데 다른 사람들 보니까 비슷한 방식으로 구현한 것 같더라...
 
파이썬으로는 .. 진짜 간단했을 것 같은데...
 
클래스를 하나 더 만들어서 구현해도 되는건가 싶었는데, 당연하다는 듯 클래스를 만들어 구현하는 다른 사람들의 코드를 보고 자바를 어떻게 다뤄야 하는지 감이 좀 더 온 느낌이다.
 
내가 자바를 너무 어렵게 생각하는 것 같기도 하고 .. 아직은 잘 모르겠다.
 
그럼 코드를 하나하나 뜯어보도록 하자.


 아이패드를 사고 나서 알고리즘 공부 방식을 바꿔봤는데, 셔틀버스를 타고 오고 가는 시간에는 코딩을 하지 못하니,

아이패드를 이용해서 로직을 어떻게 짤지를 미리 짜놓고, 집에와서 구현만 하는 방식으로 공부법을 바꿨다.

하지만, 자바로는 구현하는 것 부터 일이니 원... ㅠㅠ

일단 시간 안에 끝내지 못한 과제는 stack으로 집어넣을 예정이고, 시간 순으로 정렬도 해야한다.

그런 뒤 반복문을 돌면서 다음 과제의 시작시간에서 현재 과제의 시작시간을 뺀 값과 현재 과제의 걸리는 시간을 비교하는 방식으로 풀 예정이다.

 

저번에 배웠던 정렬 방법을 이용해서 정렬을 해보았다.

좀 더 간단하게 하는 방법이 있을 것 같지만, 이 방법도 인트로 형 변환 하는게 길게 보여서 그렇지 그렇게 오래 걸리는 작업은 아니었다.



정작 로직은 그렇게 어렵지 않았다. 다만 Stack을 자바에서는 처음 써보고, 새로운 객체를 만들어서 풀이해야 한다는 생각도 바로 하지 못해서...

파이썬은 그냥 리스트에 다 들어갔단말이죠...


이렇게 클래스를 이용해 객체를 만들어주면 자유롭게 자료형을 정해서 넣어줄 수 있다는 말씀!!

이게 가능하면 사실상 파이썬의 리스트보다 오히려 더 편한거 아닌가 싶은데...

마구 남용하다가 아마 조만간 메모리초과라든가 뭔가 호되게 당할 것 같지만 일단 자바를 대하는데에 있어서 장애물이 하나 벗겨진 것 같은 기분입니다

자바... 알고리즘 꼭 기초 단계 박살내주도록 하겠습니다

https://school.programmers.co.kr/learn/courses/30/lessons/181188

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


버스타고 집에 돌아오는 길에 일단 알고리즘을 어떻게 짤지 고민을 좀 해보게 되는 문제였습니다.

그래서, 기초 알고리즘이라고 하기에는... 좀 그렇지 않나 싶긴 하지만 그래도 Arrays.sort를 구현해볼 수 있는 문제였기에 넣었습니다!


일단 간단하게 로직을 생각해 보았습니다.

시작 지점으로 정렬을 하면 가장 빠르게 시작하는 타겟은 무조건 총을 쏴야할거고, 가능한 그 지점과 겹치는 애가 많게 쏴야합니다.

하지만, 선택한 타겟의 시작지점에서 끝 지점까지의 구간 중 겹치는게 아무리 많더라도, 겹치는 타겟의 구간이 종료되면 같이 거기서 타겟을 쏴야합니다.

왜냐면, 시작 지점으로 정렬을 했기 때문에, 겹쳤던 타겟의 구간을 지나버리면 어차피 다시 돌아와 한번 더 쏴야하기 때문이죠


그래서 선택한 구간 사이에 있는 타겟들을 차례대로 선택하고, 동시에 선택한 구간보다 더 빨리 끝나는 애가 있으면 가능한 구간을 좁혀준다! 가 포인트가 되겠습니다.

그럼 이제 배열을 정렬을 해야 할텐데, 아직 자바에 익숙하지 않아 고생 좀 했습니다...

import java.util.*;
class Solution {
    public int solution(int[][] targets) {
        int answer = 0;
        
        Arrays.sort(targets, (el1, el2)->{
            if(el1[0] == el2[0]){
                return Integer.compare(el1[1], el2[1]);
            } else {
                return Integer.compare(el1[0], el2[0]);
            }
        });
        boolean check = true;
        int start_num = targets[0][0];
        int end_num = targets[0][1];
        if(targets.length == 1){
            answer = 1;
        }
        for(int i=1; i<targets.length; i++){
            if (check == true){              
                check = false;
            } 
                if (targets[i][0] < end_num){
                    end_num = end_num > targets[i][1] ? targets[i][1] : end_num;
                } else{
                    answer += 1;
                    start_num = targets[i][0];
                    end_num = targets[i][1];
                    check = true;
                    if(i == targets.length-1){
                        check = false;
                    }
                    
                    
                    
                }
            }
        if (check == false){
            answer++;
        }
            
        
        
        return answer;
    }
}

https://school.programmers.co.kr/learn/courses/30/lessons/172928

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 
N, S, E, W 값을 받아 해당 방향으로 주어진 숫자만큼 이동하는 문제입니다.
 
4 방향으로 이동을 하는 간단한 문제지만, 왠지 쉽게 풀리지 않았습니다.
 
방향과 이동 횟수가 String으로 주어지는데, 그걸 split 하는 과정에서 [N, S, E, W] 값이 String으로 들어오기 때문에,
 
그걸 direction == "S" 와 같이 비교를 해주니 값이 계속 false가 나와 풀리지 않았습니다.
 
문자열과 문자열을 비교할 때는 == 연산을 쓰는 것이 아니라 equals로 비교를 해야 제대로 된 답이 나옵니다.
 
문제를 풀고 나서 다른 사람들은 자바로 어떻게 문제를 풀었는지 확인해보니 charAt(0) 을 이용하여 char로 바꿔준 뒤 값을 비교하는 방법을 사용하기도 하였습니다.

 

class Solution {
    public int[] solution(String[] park, String[] routes) {
        int[] answer = {};
        int si = 0;
        int sj = 0;
        int[] di = {-1, 1, 0, 0};
        int[] dj = {0, 0, -1, 1};
        int d = 0;
        for(int i = 0; i < park.length; i++){
            String row = park[i];
            for(int j = 0; j < row.length(); j++){
                if (row.charAt(j) == 'S'){
                    si = i;
                    sj = j;
                }
            }
        }
        int ci = si;
        int cj = sj;
        for(String op : routes){
            String direction = op.split(" ")[0];
            System.out.println(direction);
            int num = Integer.valueOf(op.split(" ")[1]);
            int ni = ci;
            int nj = cj;
            if (direction.equals("N")){
                d = 0;
            } else if(direction.equals("S")){
                d = 1;
            } else if (direction.equals("W")){
                d = 2;
            } else if (direction.equals("E")){
                d = 3;
            }
            for(int i=0; i<num; i++){
                ni += di[d];
                nj += dj[d];
                if (ni < 0 || ni >= park.length || nj < 0 || nj >=park[0].length()){
                    break;
                } else if(park[ni].charAt(nj) == 'X') {
                    break;
                }
                if (i == num-1){
                    ci = ni;
                    cj = nj;
                }
            }
        }
        answer = new int[2];
        answer[0] = ci;
        answer[1] = cj;
        return answer;
    }
}

 

+ Recent posts