
/*
문제 분석
1. 정보
- 문자열 S가 입력됨
- 첫글자를 X라 지정
- 문자열을 왼쪽에서 오른쪽으로 읽으면서, X와 X가 아닌 다른 글자들이 나온 횟수를 각각 셈
- 처음으로 두 횟수가 같아지는 순간 멈추고, 해당 위치까지의 문자열을 분리
- S에서 분리한 문자열을 빼고 남은 부분에 대해서 해당 과정 반복
- 만약 두 횟수가 다른 상태에서 더 이상 읽을 글자가 없다면 읽은 문자열 분리 후 종료
2. 목표
- S가 주어질 때, 분리한 문자열의 개수 리턴
3. 제약 조건
- 1 <= S의 길이 <= 10000
- S는 영어 소문자로 이루어져 있음
풀이
1. 아이디어
- S의길이가 10000 이므로 while문 사용해도 충분
- 첫 글자를 char 형태로 받음
- 해당 글자의 개수 ++
- 이후 조건에 맞을때 까지 다음 글자를 비교하여 개수에 더함
- 두 개수가 같다면 해당 인덱스 while문 빠져나오고, answer++
- 여기서 두 while의 ()에 들어갈 조건은 idx = 0으로 설정이후, idx < s.length()일때까지.
*/
class Solution {
public int solution(String s) {
int answer = 0;
int idx = 0;
int[] sum;
char first;
while (idx < s.length()) {
sum = new int[2];
first = s.charAt(idx++);
sum[0]++;
while (idx < s.length()) {
if (s.charAt(idx++) == first) {
sum[0]++;
} else {
sum[1]++;
}
if (sum[0] == sum[1]) {
break;
}
}
answer++;
}
return answer;
}
}
/*
문제 분석
1. 정보
- 휴대폰 자판은 하나의 키게 여러 개의 문자가 할당 될 수 있음
- 예로, 1번 키에 "A","B","C" 순서대로 할당되어 있다면, 3번 누르면 C가 되는 방식
- 같은 규칙을 적용해 만든 휴대폰 자판이 있음
- 같은 문자가 자판 전체에 여러 번 할당 된 경우도 있고,
- 키 하나에 같은 문자가 여러번 할당 된 경우도 있음
- 아예 할당되지 않은 경우도 있음
2. 목표
- 해당 자판을 이용해 특정 문자열을 작성할 때, 키를 최소 몇 번 눌러야 그 문자열을 작성할 수 있는지 출력
- 만약 문자열을 만들 수 없다면, -1을 출력
3. 제약 조건
- 1 <= 자판의 길이 <= 100
- 1 <= 특정 자판의 문자열 길이 <= 100
- 각 자판의 문자열의 길이는 다를 수 있음
- 각 원소는 알파벳 대문자로 이루어져 있음
- 1 <= 목표 문자열 개수 <= 100
- 1 <= 목표 문자열의 길이 <= 100
풀이
1. 아이디어
- 해당 알파벳을 뽑는데 필요한 최소 누름 횟수를 저장하기 위한 배열을 선언
- click[] = new int[26]으로 하고, 최대 100번 눌러야 뽑을 수 있는 경우의 수가 있기 때문에, 101로 초기화
- keymap의 문자열을 다 순회
- 해당 keymap의 문자를 하나씩 꺼내 click[] 과 idx + 1을 비교, 더 작은 값으로 업데이트.
- 모든 keymap이 끝나면, target을 모두 순회
- target의 문자열에서 문자를 하나씩 뽑음
- 문자에 해당하는 click의 값이 101일 경우, -1 값 저장
- 101이 아니면 sum에 해당 값을 더함
- 모든 문자를 뽑은 후 answer배열에 sum 값 저장
*/
class Solution {
public int[] solution(String[] keymap, String[] targets) {
int[] answer = new int[targets.length];
int[] click = new int[26];
Arrays.fill(click, 101);
for (int i = 0; i < keymap.length; i++) {
for (int j = 0; j < keymap[i].length(); j++) {
int idx = keymap[i].charAt(j) - 'A';
click[idx] = Math.min(click[idx], j + 1);
}
}
for (int i = 0; i < targets.length; i++) {
int sum = 0;
for (int j = 0; j < targets[i].length(); j++) {
int idx = targets[i].charAt(j) - 'A';
if (click[idx] == 101) {
sum = -1;
break;
} else {
sum += click[idx];
}
}
answer[i] = sum;
}
return answer;
}
}
/*
문제 분석
1. 정보
- 두 문자열 S, skip, 자연수 index가 주어질 때, 아래 규칙에 따라 문자열은 만듬
- 문자열 S의 각 알파벳을 index만큼 뒤의 알파벳으로 바꿔줌
- index 만큼의 뒤의 알파벳이 z를 넘어갈 경우 다시 a로 돌아감
- skip에 있는 알파벳은 제외하고 건너뜀
2. 목표
- 위 내용이 주어질 때, 규칙대로 s를 변환한 결과를 return
3. 제약 조건
- 5 <= s <= 50
- 1 <= skip <= 10
- s와 skip은 소문자로만 이루어짐
- skip에 포함되는 알파벳은 s에 없음
- 1 <= index <= 20
풀이
1. 아이디어
- 최대 50 * 20 -> 1000 바로 index를 더해주지 않고 하나씩 풀어나가도 가능
- 먼저 boolean[]배열 선언해 해당 알파벳이 스킵되는지 유무 설정
- 스킵 된다면 index - 1 하지 않고 넘어감
- index = 0 이 될때가 변환된 암호
*/
class Solution {
public static String solution(String s, String skip, int index) {
StringBuilder sb = new StringBuilder();
boolean[] check = new boolean[26];
for (int i = 0; i < skip.length(); i++) {
check[skip.charAt(i) - 'a'] = true;
}
for (int i = 0; i < s.length(); i++) {
int cnt = index;
int cur = s.charAt(i) - 'a';
while (cnt > 0) {
if (!check[(cur + 1) % 26]) {
cnt--;
}
cur = (cur + 1) % 26;
}
sb.append((char) (cur + 'a'));
}
return sb.toString();
}
}
/*
문제 분석
1. 정보
- 조리 된 재료를 조리된 순서대로 상수가 아래서 위로 햄버거를 쌓음
- 정해진 순서는 빵-야채-고기-빵으로 쌓인 햄버거만 포장 가능
- 재료의 높이는 무시
- 예로, 재료의 순서가 [야채 빵 빵 야채 고기 빵 야채 고기 빵] 일때
- 상수는 6번째 재료가 쌓였을 때, 3번째 재료부터 여섯 번째 재료를 이용하여 햄버거를 포장
- 9번째 재료가 쌓였을 때, 2번째 재료와 7 ~ 9 번째 재료를 이용하여 햄버거를 포장
- 1 : 빵
- 2 : 야채
- 3 : 고기
- 를 의미
- 즉 1 2 3 1 순으로 들어올때, 햄버거 포장 가능
2. 목표
- 포장 가능한 햄버거의 개수를 출력
3. 제약 조건
- 1 <= 재료의 길이 <= 1,000,000
- 재료는 1, 2, 3 중 하나의 값
풀이
1. 아이디어
- Stack 사용
- 재료를 하나씩 Stack에 추가
- Stack의 마지막 4개 요소가 1 2 3 1 순서라면
- 마지막 4개 요소 제거
- 햄버거 포장++
- Stack에서 모든 햄버거를 포장 가능할 때 까지 반복
*/
class Solution {
public int solution(int[] ingredient) {
Stack<Integer> stack = new Stack<>();
int[] seq = {1, 3, 2, 1};
int answer = 0;
for (int cur : ingredient) {
stack.push(cur);
if (stack.size() >= 4) {
boolean flag = true;
for (int i = 0; i < 4; i++) {
if (stack.get(stack.size() - (i + 1)) != seq[i]) {
flag = false;
}
}
if (flag) {
answer++;
for (int i = 0; i < 4; i++) {
stack.pop();
}
}
}
}
return answer;
}
}
/*
문제 분석
1. 정보
- 성격 유형 검사는 다음과 같은 4개 지표로 셩격 유형을 구분함
- 1번 지표 : 라이언형(R), 튜브형(T)
- 2번 지표 : 콘형(C), 프로도형(F)
- 3번 지표 : 제이지형(J), 무지형(M)
- 4번 지표 : 어피치형(A), 네오형(N)
- 4개의 지표가 있으므로, 성격 유형은 총 16가지가 나올 수 있음
- 검사지에는 총 N개의 질문이 있고, 아래와 같은 7개의 선택지가 존재
- 매우 비동의
- 비동의
- 약간 비동의
- 모르겠음
- 약간 동의
- 동의
- 매우 동의
- 각 질문은 1가지 지표로 성격 유형 점수를 판단
- 예를 들어,
- 매우 비동의 : 네오형 3점
- 비동의 : 네오형 2점
- 약간 비동의 : 네오형 1점
- 모르겠음 : 0점
- 약간 동의 : 어피치형 1점
- 동의 : 어피치형 2점
- 매우 동의 : 어피치형 3점
- 질문에 따라 비동의와 동의의 형이 주어짐
- 검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은 점수를 받은 성격 유형이 검사자의 성격 우형
- 만약 하나의 지표에서 각 성격 유형 점수가 같다면, 사전순으로 빠른 성격 유형을 선택
2. 목표
- 검사자의 성격 유형 검사 결과를 지표 번호 순서대로 return
3. 제약 조건
- 1 <= 검사 질문 지표 <= 1000
- "AB"형태로 들어옴
- 왼쪽 char가 비동의 관련, 오른쪽 char가 동의 관련
- 검사의 길이 = 검사 질문 지표의 길이
풀이
1. 아이디어
- 단순 구현
- 먼저 int[] 배열을 만들음. 대문자 알파벳의 개수를 길이로 하는 배열을 만들어 점수를 담음
- survey의 길이 만큼 for문 수행
- i번째의 choice 값을 가져옴.
- case문을 만들어 수행
- 1 : 왼쪽 char값에 해당하는 배열에 3 추가
- 2 : 왼쪽 char값에 해당하는 배열에 2 추가
- 3 : 왼쪽 char값에 해당하는 배열에 1 추가
- 4 : 점수 추가 없음
- 5 : 오른쪽 char값에 해당하는 배열에 1 추가
- 6 : 오른쪽 char값에 해당하는 배열에 2 추가
- 7 : 오른쪽 char값에 해당하는 배열에 3 추가
- 모든 survey 가 수행되었으면,
- R과 T 비교
- C와 F 비교
- J와 M 비교
- A와 N 비교
- 하여 더 큰값, 값이 같다면 사전순으로 빠른 값을 answer에 추가
- answer return
*/
class Solution {
public String solution(String[] survey, int[] choices) {
int[] score = new int[26];
for (int i = 0; i < survey.length; i++) {
int left = survey[i].charAt(0) - 'A';
int right = survey[i].charAt(1) - 'A';
switch (choices[i]) {
case (1) -> score[left] += 3;
case (2) -> score[left] += 2;
case (3) -> score[left] += 1;
case (5) -> score[right] += 1;
case (6) -> score[right] += 2;
case (7) -> score[right] += 3;
}
}
StringBuilder sb = new StringBuilder();
if (score['R' - 'A'] >= score['T' - 'A']) {
sb.append("R");
} else {
sb.append("T");
}
if (score['C' - 'A'] >= score['F' - 'A']) {
sb.append("C");
} else {
sb.append("F");
}
if (score['J' - 'A'] >= score['M' - 'A']) {
sb.append("J");
} else {
sb.append("M");
}
if (score['A' - 'A'] >= score['N' - 'A']) {
sb.append("A");
} else {
sb.append("N");
}
return sb.toString();
}
}
/*
문제 분석
1. 정보
- 머쓱이는 작성한 코드를 컴퓨터 바탕화면에 아무 위치에 저장
- 작성한 코드가 많아짐에 따라, 프로그래머스에서 작성했던 코드는 바탕화면에서 삭제하기로 함
- 바탕화면은 각 칸이 정사각형인 격자
- 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어짐
- (0,0)이 시작
- 빈칸은 .
- 파일이 있는 칸은 #
- 드래그를 하면 파일을 선택할 수 있고, 선택한 파일을 삭제할 수 있음
- 드래그는 다음과 같음
- 격자점 S(lux,luy)에서 E(rdx,rdy)까지 드래그 했을 경우,
- 점 S에서 점 E로 드래그한다 라고 표현
- 드래그 한 거리 : |rdx - lux| + |rdy - luy|
2. 목표
- 드래그 한 거리가 최소가 되는 값의 lux, luy, rdx, rdy를 출력
3. 제약 조건
- 1 <= 격자판의 높이 <= 50
- 1 <= 격자판의 너비 <= 50
- 바탕화면에는 적어도 하나의 파일이 있음
풀이
1. 아이디어
- lux, luy, rdx, rdy를 선언
- wallpaper 배열을 왼쪽 위부터 오른쪽 아래까지 순차적으로 방문
- 해당 격자에 #이 있다면, 위 4개에 적절히 업데이트
- 모든 격자판을 방문한 이후, 위 4개의 정보를 활용해 드래그 범위를 구함
*/
class Solution {
public int[] solution(String[] wallpaper) {
int lux = 51;
int luy = 51;
int rdx = 0;
int rdy = 0;
for (int i = 0; i < wallpaper.length; i++) {
for (int j = 0; j < wallpaper[i].length(); j++) {
if (wallpaper[i].charAt(j) == '#') {
lux = Math.min(lux, i);
luy = Math.min(luy, j);
rdx = Math.max(rdx, i + 1);
rdy = Math.max(rdy, j + 1);
}
}
}
return new int[]{lux, luy, rdx, rdy};
}
}