Programmers
[프로그래머스 Level.3] 110 옮기기 (월간 코드 챌린지 시즌2) (Java)
Devtraces
2023. 3. 8. 14:51
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/77886
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
코딩테스트 연습 > 월간 코드 챌린지 시즌2 > 110 옮기기
문제 설명
0과 1로 이루어진 어떤 문자열 x에 대해서, 당신은 다음과 같은 행동을 통해 x를 최대한 사전 순으로 앞에 오도록 만들고자 합니다.
- x에 있는 "110"을 뽑아서, 임의의 위치에 다시 삽입합니다.
예를 들어, x = "11100" 일 때, 여기서 중앙에 있는 "110"을 뽑으면 x = "10" 이 됩니다. 뽑았던 "110"을 x의 맨 앞에 다시 삽입하면 x = "11010" 이 됩니다.
변형시킬 문자열 x가 여러 개 들어있는 문자열 배열 s가 주어졌을 때, 각 문자열에 대해서 위의 행동으로 변형해서 만들 수 있는 문자열 중 사전 순으로 가장 앞에 오는 문자열을 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한사항
- 1 ≤ s의 길이 ≤ 1,000,000
- 1 ≤ s의 각 원소 길이 ≤ 1,000,000
- 1 ≤ s의 모든 원소의 길이의 합 ≤ 1,000,000
입출력 예
s | result |
["1110","100111100","0111111010"] | ["1101","100110110","0110110111"] |
입출력 예 설명
입출력 예 #1
- 다음 그림은 "1110"을 "1101"로 만드는 과정을 나타낸 것입니다.

- "1101"보다 사전 순으로 더 앞에 오는 문자열을 만들 수 없으므로, 배열에 "1101"을 담아야 합니다.
- 다음 그림은 "100111100"을 "100110110"으로 만드는 과정을 나타낸 것입니다.

- "100110110"보다 사전 순으로 더 앞에 오는 문자열을 만들 수 없으므로, 배열에 "100110110"을 담아야 합니다.
- 그림에 나온 방식 말고도 다른 방법으로 "100110110"을 만들 수 있습니다.
- 다음 그림은 "0111111010"을 "0110110111"로 만드는 과정을 나타낸 것입니다.

- "0110110111"보다 사전 순으로 더 앞에 오는 문자열을 만들 수 없으므로, 배열에 "0110110111"을 담아야 합니다.
- 그림에 나온 방식 말고도 다른 방법으로 "0110110111"을 만들 수 있습니다.
나의 코드
class Solution {
// "110"을 전부 뽑아서 뒤에서부터 앞으로 가면서 1보단 앞에 0보단 뒤에 위치하게 한다.
public String[] solution(String[] s) {
String[] answer = new String[s.length];
for(int i=0; i<s.length; i++) {
int cnt = 0;
StringBuilder sb = new StringBuilder();
for(int j=0; j<s[i].length(); j++) {
sb.append(s[i].charAt(j));
if(sb.length() < 3) continue;
if("110".equals(sb.substring(sb.length()-3))) {
sb.setLength(sb.length()-3);
cnt++;
}
}
// "110"을 넣을 위치 찾기
int idx = sb.length();
while(idx > 0) {
if(sb.charAt(idx-1) == '1')
idx--;
else
break;
}
sb.insert(idx, "110".repeat(cnt));
answer[i] = sb.toString();
}
return answer;
}
}
풀이
- 110을 뽑아 사전 순으로 가장 앞에 오도록 다시 넣는 방법은 110을 순서대로 전부 뽑은 후에 뽑은 문자열의 맨 뒤에서부터 앞으로 가면서 1이라면 계속 앞으로 가다가 0이 나오면 0 뒤에 넣으면 된다.
- 우선 주어진 문자열 s를 for문을 돌면서 "110"이 나오면 제거하고 "110"의 개수를 카운팅한다.
- 블록 처럼 중간에 "110"을 제거했다면 "110"을 제거하고 뒤의 문자열이 땡겨져서 이어진 문자열에 다시 "110"이 생기는 것도 체크하기 위해 StringBuilder를 만들어 s의 문자를 하나씩 추가하며 뒤에서부터 세 글자가 "110"이 되면 제거하고 카운팅한 뒤 다시 나머지 s의 문자들을 추가하여 "110"이 되면 제거하고 카운팅 하는 방식으로 체크한다.
- 이제 "110"을 모두 제거한 나머지 문자열을 가지고 위치를 찾은 뒤에 해당 위치에 카운팅한 "110"의 개수만큼 "110"을 채워넣는다.
- "110"을 모두 제거한 나머지 문자열의 길이는 StringBuilder의 길이이므로 해당 위치의 마지막 위치부터 1인지 0인지 체크하여 1이라면 인덱스를 1씩 계속 줄이다가 0이 나오면 멈춘다.
- 이제 0 뒤의 위치에 repeat()를 이용하여 카운팅 한 "110"의 개수만큼 StringBuilder에 insert()를 이용하여 "110"을 넣으면 사전순으로 가장 앞에 오도록 완성된다.
- 해당 StringBuilder를 String으로 변환하여 answer에 저장하고 반환한다.