코테/프로그래머스

[프로그래머스/Level3] 표 편집 (JAVA)

imname1am 2024. 7. 24. 17:08
반응형

📖 문제

 

프로그래머스

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

programmers.co.kr

 

 

 

💡  풀이 방식

• 스택

필요 자료구조
- 이전 노드 위치 기억용 배열 preArr
- 다음 노드 위치 기억용 배열 nextArr
- 삭제한 위치의 노드 정보 저장용 스택

 

. preArr, nextArr 배열을 사용한다.

  - 각 인덱스에 해당하는 위치의 이전 노드 위치, 다음 노드 위치를 기억한다.

  - 맨 마지막 노드의 다음 노드는 -1로 설정해둔다.

 

. 크기 n만큼 'O' 문자열을 만든다.

 

. 각 명령에 맞는 작업을 수행한다.

1. 위로 이동하는 경우, 값만큼 현재 위치 k를 위로 이동한다.

int v = Integer.parseInt(cmd[i].substring(2));
while(v --> 0) {
    k = preArr[k];
}

 

 

2. 아래로 이동하는 경우, 값만큼 k를 아래로 이동한다.

else if(c == 'D') {
    int v = Integer.parseInt(cmd[i].substring(2));
    while(v --> 0) {
        k = nextArr[k];
    }
}

 

 

3. 현재 위치를 삭제하는 경우

- 삭제하는 노드의 정보를 스택에 저장한다. (복구 시 가장 최근 삭제된 값부터 복구하므로)

- 만약 현재 위치 k의 이전 위치가 맨 마지막 (-1)이 아니라면, 현재 노드를 삭제한 후 앞뒤를 연결한다. (연결 리스트가 필요한 이유)

- 만약 현재 위치 k의 다음 위치가 맨 마지막( -1)이 아니라면, 현재 노드를 삭제한 후 앞뒤를 연결한다.

- k 위치에서 삭제가 발생했으므로, StringBuilder의 k 위치를 X 표시로 변경한다.

- 만약 삭제된 행이 가장 마지막 행인 경우 바로 윗 행을 선택한다. 마지막 행이 아니라면, 다음 행을 선택하도록 한다.

 

4. 가장 최근 삭제된 행을 되돌린다.

 - 스택에서 가장 최근에 저장된 노드 정보를 가져온다. 

 - 이전 위치 배열의 다음 값, 다음 위치 배열의 이전 값으로 현재 값을 저장해 연결 정보를 복구한다.

 - 'O' 문자로 변경한다.

 

 

stack.push(new Node(preArr[k], k, nextArr[k]));  // 삭제하는 노드 정보 스택에 추가하기
                
if(preArr[k] != -1)    nextArr[preArr[k]] = nextArr[k]; // 현재 노드 삭제 후 앞뒤 연결
if(nextArr[k] != -1)   preArr[nextArr[k]] = preArr[k];

sb.setCharAt(k, 'X');

if(nextArr[k] != -1)   k = nextArr[k];
else                   k = preArr[k];   // 마지막 행인 경우에 바로 윗 행 선택

 

 

 

💥 유의사항

- 현재 인덱스의 이전 행과 다음 행 정보를 모두 저장해 둬야 한다.

- 마지막 행과 첫 행은 연결되어 있다.

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.util.*;
 
class Solution {
    public String solution(int n, int k, String[] cmd) {
        int[] preArr = new int[n];  // 이전 노드 위치 기억용 배열
        int[] nextArr = new int[n]; // 다음 노드 위치 기억용 배열
        
        for(int i = 0 ; i < n ; i++) {
            preArr[i]  = i-1;
            nextArr[i] = i+1;
        }
        nextArr[n-1= -1;
        
        Stack<Node> stack = new Stack<>(); // ☀️ 삭제한 위치의 노드 정보 저장용 스택
        StringBuilder sb = new StringBuilder("O".repeat(n));    // 크기 n만큼 'O' 문자열 만들기
                
        for(int i = 0 ; i < cmd.length ; i++) {
            char c = cmd[i].charAt(0);
            
            // 위로 이동
            if(c == 'U') {
                int v = Integer.parseInt(cmd[i].substring(2));
                while(v --> 0) {
                    k = preArr[k];
                }
            }
            // 아래로 이동
            else if(c == 'D') {
                int v = Integer.parseInt(cmd[i].substring(2));
                while(v --> 0) {
                    k = nextArr[k];
                }
            }
            // 현재 위치 삭제
            else if(c == 'C') {
                stack.push(new Node(preArr[k], k, nextArr[k])); // 삭제하는 노드 정보 스택에 추가하기
                
                if(preArr[k] != -1)    nextArr[preArr[k]] = nextArr[k]; // 현재 노드 삭제 후 앞뒤 연결
                if(nextArr[k] != -1)   preArr[nextArr[k]] = preArr[k];
                
                sb.setCharAt(k, 'X');
                
                if(nextArr[k] != -1)   k = nextArr[k];
                else                   k = preArr[k];   // 마지막 행인 경우에 바로 윗 행 선택
            }
            // 가장 최근 삭제된 행 되돌리기
            else if(c == 'Z') {
                Node now = stack.pop(); // 가장 최근 삭제한 노드 정보 가져오기
                
                if(now.pre != -1)  nextArr[now.pre] = now.cur;  // 연결 정보 복구
                if(now.next != -1) preArr[now.next] = now.cur;
                sb.setCharAt(now.cur, 'O');
            }
        }
              
        return sb.toString();
    }
}
 
class Node {
    int pre, cur, next;
    
    public Node(int pre, int cur, int next) {
        this.pre = pre; // 이전 노드
        this.cur = cur; // 현재 위치
        this.next = next; // 다음 노드
    }
}
cs

 

 

➕ 다른 풀이 방식

- 삭제 여부를 boolean형으로 나타내서 출력할 때 활용하는 방식을 사용하셨다. (내가 처음에 생각했던  방식)

 

Programmers - 표 편집(Java)

https://programmers.co.kr/learn/courses/30/lessons/81303 코딩테스트 연습 - 표 편집 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z"] "OOOOXOOO" 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z","U 1","C"] "OOXOXOOO" programmers.co.kr 풀이 삭제

jangcenter.tistory.com

 

 

- 멋진 풀이,,

 

프로그래머스 level 3 ) 표 편집

"U X": 현재 선택된 행에서 X칸 위에 있는 행을 선택합니다."D X": 현재 선택된 행에서 X칸 아래에 있는 행을 선택합니다."C" : 현재 선택된 행을 삭제한 후, 바로 아래 행을 선택합니다. 단, 삭제된 행

velog.io


💦 어려웠던 점

- 현재 위치 삭제(C)와 가장 최근 삭제된 행 되돌리기(Z) 가 어려웠다.

 

🧐 새로 알게 된 내용

- 가장 마지막으로 삭제된 위치의 정보를 저장할 때 스택을 사용할 아이디어를 얻게 되었다.

- LinkedList의 원소 탐색 시 시간 복잡도 O(N) * 1차원 배열 사용해 인덱스로 접근 시 시간 복잡도 O(1)

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

✔ 풀이 참고

 

[프로그래머스]표 편집 - JAVA

** 풀이가 추가되었습니다. 추가된 풀이가 정확한 풀이입니다. ** [프로그래머스]표 편집 코딩테스트 연습 - 표 편집 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z"] "OOOOXOOO" 8 2 ["D 2","C","U 3","C","D 4","C","U 2","

moonsbeen.tistory.com

 

[프로그래머스] 2021 카카오 채용연계형 인턴십 - 표 편집 (Java)

코딩테스트 연습 - 표 편집 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z"] "OOOOXOOO" 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z","U 1","C"] "OOXOXOOO" programmers.co.kr 문제 설명 [본 문제는 정확성과 효율성 테스트 각각

bellog.tistory.com

 

 

그림 참고

 

Programmers - 표 편집(Java)

https://programmers.co.kr/learn/courses/30/lessons/81303 코딩테스트 연습 - 표 편집 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z"] "OOOOXOOO" 8 2 ["D 2","C","U 3","C","D 4","C","U 2","Z","Z","U 1","C"] "OOXOXOOO" programmers.co.kr 풀이 삭제

jangcenter.tistory.com

 

반응형