1. 옹알이
문제 설명
머쓱이는 태어난 지 6개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음을 최대 한 번씩 사용해 조합한(이어 붙인) 발음밖에 하지 못합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.
제한사항
- 1 ≤ babbling의 길이 ≤ 100
- 1 ≤ babbling[i]의 길이 ≤ 15
- babbling의 각 문자열에서 "aya", "ye", "woo", "ma"는 각각 최대 한 번씩만 등장합니다.
- 즉, 각 문자열의 가능한 모든 부분 문자열 중에서 "aya", "ye", "woo", "ma"가 한 번씩만 등장합니다.
- 문자열은 알파벳 소문자로만 이루어져 있습니다.
입출력 예
babbling result
["aya", "yee", "u", "maa", "wyeoo"] | 1 |
["ayaye", "uuuma", "ye", "yemawoo", "ayaa"] | 3 |
풀이
이미 풀어봤던 문제라 다시 쉽게 풀었다.
각 문자열에서 “aya”, “ye”, “woo”, “ma”는 한번씩 등장하기 때문에 replace를 사용해서 공백으로 치환해준다.
그리고 replaceAll을 사용해서 “ “ → “” 으로 치환해주고 문자열이 비었다면 발음이 가능/ 문자열에 다른 텍스트가 남아있다면 발음이 불가능하다고 판단할 수 있다.
만약 “ayaetgyewoodma” 라는 문자열로 예시를 들어본다면
“ etgyewoodma” → “ etg woodma” → “ etg dma” → “ etg d “ → “etgd” 가 남을 것이다.
이 문자열은 발음이 불가능하다고 판단할 수 있다.
정답
class Solution {
public int solution(String[] babbling) {
int answer = 0;
for(String s : babbling) {
s = s.replace("aya"," ");
s = s.replace("ye"," ");
s = s.replace("woo"," ");
s = s.replace("ma"," ");
s = s.replaceAll(" ","");
if(s.equals("")) answer++;
}
return answer;
}
}
2. 평행
문제 설명
점 네 개의 좌표를 담은 이차원 배열 dots가 다음과 같이 매개변수로 주어집니다.
- [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.
제한사항
- dots의 길이 = 4
- dots의 원소는 [x, y] 형태이며 x, y는 정수입니다.
- 0 ≤ x, y ≤ 100
- 서로 다른 두개 이상의 점이 겹치는 경우는 없습니다.
- 두 직선이 겹치는 경우(일치하는 경우)에도 1을 return 해주세요.
- 임의의 두 점을 이은 직선이 x축 또는 y축과 평행한 경우는 주어지지 않습니다.
입출력 예
dots result
[[1, 4], [9, 2], [3, 8], [11, 6]] | 1 |
[[3, 5], [4, 1], [2, 4], [5, 10]] | 0 |
풀이
비교 횟수가 3번밖에 되지 않아서 하드 코딩으로 풀었다.
[0,1][2,3] / [0,2][1,3] / [0,3][1,2] 의 기울기를 비교해서 같은 경우 1을, 다른 경우 0을 return했다.
기울기 계산 할 때 혹시나 X 좌표가 같으면 분모가 0이 돼서 에러가 발생하기 때문에 Double.POSITIVE_INFINITY를 반환함으로서 예외 처리를 해줬다.
계속 TestCase 2번만 오류가 나서 한참 생각했는데 grad 메서드 안에서 (double)로 형변환을 안 한 상태로 계산해서 return 했기 때문이었다 ㅎㅎ…
정답
import java.util.*;
class Solution {
public int solution(int[][] dots) {
int answer = 0;
if(grad(dots[0], dots[1])==grad(dots[2], dots[3])) return 1;
else if(grad(dots[0], dots[2])==grad(dots[1], dots[3])) return 1;
else if(grad(dots[0], dots[3])==grad(dots[1], dots[2])) return 1;
return answer;
}
static double grad(int[] a, int[] b) {
if(a[0]==b[0]) return Double.POSITIVE_INFINITY;
return (double)(a[1]-b[1])/(double)(a[0]-b[0]);
}
}
3. 겹치는 선분의 길이
문제 설명
선분 3개가 평행하게 놓여 있습니다. 세 선분의 시작과 끝 좌표가 [[start, end], [start, end], [start, end]] 형태로 들어있는 2차원 배열 lines가 매개변수로 주어질 때, 두 개 이상의 선분이 겹치는 부분의 길이를 return 하도록 solution 함수를 완성해보세요.
lines가 [[0, 2], [-3, -1], [-2, 1]]일 때 그림으로 나타내면 다음과 같습니다.

선분이 두 개 이상 겹친 곳은 [-2, -1], [0, 1]로 길이 2만큼 겹쳐있습니다.
제한사항
- lines의 길이 = 3
- lines의 원소의 길이 = 2
- 모든 선분은 길이가 1 이상입니다.
- lines의 원소는 [a, b] 형태이며, a, b는 각각 선분의 양 끝점 입니다.
- 100 ≤ a < b ≤ 100
입출력 예
lines result
[[0, 1], [2, 5], [3, 9]] | 2 |
[[-1, 1], [1, 3], [3, 9]] | 0 |
[[0, 5], [3, 9], [1, 10]] | 8 |
풀이
겹치는 선분의 길이를 더하고 중복으로 더해지는 구간을 빼야하나? 근데 이걸 어떻게 계산해야 하지?
이런 생각에 사로잡혀 다른 풀이는 생각도 못 하고 로직을 어떻게 짜야할지에만 집중하니 문제가 풀리지 않았다.
결국 도저히 모르겠어서 이런 저런 구글링을 했는데 “길이를 구한다”가 아닌 “선분이 지나가는 점을 찾는다” 가 정답이었다.
점의 범위가 -100~100이기 때문에 크기가 200인 배열을 만들고 선분에 포함되는 점은 값을 +1 해준다.
여러 번 지나가는 점은 당연히 값이 2 이상이 될 것이다.
그리고 마지막에 배열을 순회하며 값이 1보다 크면 answer++ 해서 return한다.
여기서 주의해야 할 점은 아래 정답 코드에서 for문 범위 설정이다.
for(int k=start; k<end; k++) {
count[k] += 1;
}
선분에 포함된 점을 체크할 때 end 까지 포함시킨다면 중간이 파여 있는 구간까지 계산이 되어버린다.
무슨 얘기인지 모르겠다면 아래 사진을 보자.


문제에서 그림으로 표현한 예제에서 선분 대신 지나가는 점만 체크한 건데 예제 상으로는 겹치는 구간이 [-2,-1], [0,1]로 길이는 2가 되어야 한다.
하지만 점으로 찍어보면 -2, -1, 0, 1 이렇게 4개의 점이 모두 값이 2로 되어서 answer = 4로 나온다.
여기서 만약 for문 범위를 end-1까지만 돌린다면

값이 2 이상인 점은 -2, 0 으로 answer = 2가 되는 것을 알 수 있다.
정답
class Solution {
public int solution(int[][] lines) {
int answer = 0;
int[] count = new int[201];
for(int[] i : lines) {
int start = i[0]+100;
int end = i[1]+100;
for(int k=start; k<end; k++) {
count[k] += 1;
}
}
for(int i : count) {
if(i>1) answer++;
}
return answer;
}
}
4. 안전지대
문제 설명
다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을 모두 위험지역으로 분류합니다.

지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는 지뢰가 매설 된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때, 안전한 지역의 칸 수를 return하도록 solution 함수를 완성해주세요.
제한사항
- board는 n * n 배열입니다.
- 1 ≤ n ≤ 100
- 지뢰는 1로 표시되어 있습니다.
- board에는 지뢰가 있는 지역 1과 지뢰가 없는 지역 0만 존재합니다.
입출력 예
board result
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]] | 16 |
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 0]] | 13 |
[[1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1]] | 0 |
풀이
위험지역을 전부 0이 아닌 값으로 바꾼 후 0의 개수만 세면 된다.
배열 순회하다가 값이 1이면 주위 값을 다 2로 바꿔준다.
이 때 1로 바꾸면 안 되는 이유는 기존 지뢰는 주변을 위험지역으로 만들지만, 위험지역의 주변은 변화가 없어야 하기 때문이다.
첫번째 표가 초기 지뢰밭이라고 가정했을 때 주변 위험지역이 두번째 표처럼 1로 바뀌면


빨간색 1도 전부 기존 지뢰라고 인식이 되서 아래처럼 전부 1로 변한단 얘기다.

그렇기 때문에 배열의 데이터가 1인 부분만 주변을 2로 바꿔준 후 마지막에 0인 값들만 count하면 된다.
정답
class Solution {
public int solution(int[][] board) {
int answer = 0;
int[] array1 = new int[]{-1, -1, -1, 1, 1, 1, 0, 0};
int[] array2 = new int[]{-1, 0, 1, 0, 1, -1, 1, -1};
for(int i=0; i<board.length; i++) {
for(int k=0; k<board[i].length; k++) {
if(board[i][k]==1) {
for(int t=0; t<8; t++) {
int dx = i+array1[t];
int dy = k+array2[t];
if(dx>=0&&dy>=0&&dx<=board.length-1&&dy<=board[i].length-1&&board[dx][dy]!=1) board[dx][dy] = 2;
}
}
}
}
for(int i=0; i<board.length; i++) {
for(int k=0; k<board[i].length; k++) {
if(board[i][k]==0) answer++;
}
}
return answer;
}
}
5. 연속된 수의 합
문제 설명
연속된 세 개의 정수를 더해 12가 되는 경우는 3, 4, 5입니다. 두 정수 num과 total이 주어집니다. 연속된 수 num개를 더한 값이 total이 될 때, 정수 배열을 오름차순으로 담아 return하도록 solution함수를 완성해보세요.
제한사항
- 1 ≤ num ≤ 100
- 0 ≤ total ≤ 1000
- num개의 연속된 수를 더하여 total이 될 수 없는 테스트 케이스는 없습니다.
입출력 예
num total result
3 | 12 | [3, 4, 5] |
5 | 15 | [1, 2, 3, 4, 5] |
4 | 14 | [2, 3, 4, 5] |
5 | 5 | [-1, 0, 1, 2, 3] |
정답
class Solution {
public int[] solution(int num, int total) {
int[] answer = new int[num];
int center = total/num;
answer[0] = center-(num-1)/2;
for(int i=1; i<num; i++) {
answer[i] = answer[i-1]+1;
}
return answer;
}
}
6. 다음에 올 숫자
문제 설명
등차수열 혹은 등비수열 common이 매개변수로 주어질 때, 마지막 원소 다음으로 올 숫자를 return 하도록 solution 함수를 완성해보세요.
제한사항
- 2 < common의 길이 < 1,000
- 1,000 < common의 원소 < 2,000
- common의 원소는 모두 정수입니다.
- 등차수열 혹은 등비수열이 아닌 경우는 없습니다.
- 등비수열인 경우 공비는 0이 아닌 정수입니다.
입출력 예
common result
[1, 2, 3, 4] | 5 |
[2, 4, 8] | 16 |
풀이
common[2]-common[1] == common[1]-common[0] 이라면 등차수열이기 때문에 배열의 마지막 원소에 공차를 더해준다.
등차수열이 아니라면 등비수열이기 때문에 다른 검증 없이 마지막 원소에 공비를 곱해준다.
결과
class Solution {
public int solution(int[] common) {
int answer = 0;
int len = common.length;
if(common[2]-common[1] == common[1]-common[0]) answer = common[len-1] + common[1]-common[0];
else answer = common[len-1] * common[1]/common[0];
return answer;
}
}
7. 분수의 덧셈
문제 설명
첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록 solution 함수를 완성해보세요.
제한사항
- 0 <numer1, denom1, numer2, denom2 < 1,000
입출력 예
numer1 denom1 numer2 denom2 result
1 | 2 | 3 | 4 | [5, 4] |
9 | 2 | 1 | 3 | [29, 6] |
풀이
주어진 분수를 우선 그냥 더한 후 유클리드 호제법을 사용해 최대공약수를 구해서 기약분수로 만들었다.
💡 유클리드 호제법
유클리드 알고리즘(Euclidean algorithm)은 2개의 자연수의 최대공약수를 구하는 알고리즘입니다. 비교대상의 두 개의 자연수 a와 b에서(단 a>b) a를 b로 나눈 나머지를 r이라고 했을때 GCD(a, b) = GCD(b, r)과 같고 "r이 0이면 그때 b가 최대공약수이다."라는 원리를 활용한 알고리즘입니다.
정답
class Solution {
public int[] solution(int numer1, int denom1, int numer2, int denom2) {
int[] answer = new int[2];
answer[0] = numer1 * denom2 + numer2 * denom1;
answer[1] = denom1 * denom2;
int gcd = getGcd(answer[0], answer[1]);
answer[0] /= gcd;
answer[1] /= gcd;
return answer;
}
public int getGcd(int a, int b) {
if (b == 0) return a;
return getGcd(b, a % b);
}
}
8. OX퀴즈
문제 설명
덧셈, 뺄셈 수식들이 'X [연산자] Y = Z' 형태로 들어있는 문자열 배열 quiz가 매개변수로 주어집니다. 수식이 옳다면 "O"를 틀리다면 "X"를 순서대로 담은 배열을 return하도록 solution 함수를 완성해주세요.
제한사항
- 연산 기호와 숫자 사이는 항상 하나의 공백이 존재합니다. 단 음수를 표시하는 마이너스 기호와 숫자 사이에는 공백이 존재하지 않습니다.
- 1 ≤ quiz의 길이 ≤ 10
- X, Y, Z는 각각 0부터 9까지 숫자로 이루어진 정수를 의미하며, 각 숫자의 맨 앞에 마이너스 기호가 하나 있을 수 있고 이는 음수를 의미합니다.
- X, Y, Z는 0을 제외하고는 0으로 시작하지 않습니다.
- 10,000 ≤ X, Y ≤ 10,000
- 20,000 ≤ Z ≤ 20,000
- [연산자]는 + 와 - 중 하나입니다.
입출력 예
quiz result
["3 - 4 = -3", "5 + 6 = 11"] | ["X", "O"] |
["19 - 6 = 13", "5 + 66 = 71", "5 - 15 = 63", "3 - 1 = 2"] | ["O", "O", "X", "O"] |
정답
class Solution {
public String[] solution(String[] quiz) {
String[] answer = new String[quiz.length];
int k = 0;
for(String s : quiz) {
String[] str = s.split(" ");
int a = 0;
if(str[1].equals("+")) {
a = Integer.parseInt(str[0])+Integer.parseInt(str[2]);
}
else {
a = Integer.parseInt(str[0])-Integer.parseInt(str[2]);
}
if(a == Integer.parseInt(str[4])) answer[k++] = "O";
else answer[k++] = "X";
}
return answer;
}
}
9. 최빈값 구하기
문제 설명
최빈값은 주어진 값 중에서 가장 자주 나오는 값을 의미합니다. 정수 배열 array가 매개변수로 주어질 때, 최빈값을 return 하도록 solution 함수를 완성해보세요. 최빈값이 여러 개면 -1을 return 합니다.
제한사항
- 0 < array의 길이 < 100
- 0 ≤ array의 원소 < 1000
입출력 예
array result
[1, 2, 3, 3, 3, 4] | 3 |
[1, 1, 2, 2] | -1 |
[1] | 1 |
정답
class Solution {
public int solution(int[] array) {
int answer = -1;
int[] count = new int[1001];
for(int i : array) {
count[i]++;
}
int max = 0;
for(int i=0; i<count.length; i++) {
if(count[i]>=max) {
if(count[i]==max) answer = -1;
else {
max = count[i];
answer = i;
}
}
}
return answer;
}
}
10. 다항식 더하기
문제 설명
한 개 이상의 항의 합으로 이루어진 식을 다항식이라고 합니다. 다항식을 계산할 때는 동류항끼리 계산해 정리합니다. 덧셈으로 이루어진 다항식 polynomial이 매개변수로 주어질 때, 동류항끼리 더한 결괏값을 문자열로 return 하도록 solution 함수를 완성해보세요. 같은 식이라면 가장 짧은 수식을 return 합니다.
제한사항
- 0 < polynomial에 있는 수 < 100
- polynomial에 변수는 'x'만 존재합니다.
- polynomial은 0부터 9까지의 정수, 공백, ‘x’, ‘+'로 이루어져 있습니다.
- 항과 연산기호 사이에는 항상 공백이 존재합니다.
- 공백은 연속되지 않으며 시작이나 끝에는 공백이 없습니다.
- 하나의 항에서 변수가 숫자 앞에 오는 경우는 없습니다.
- " + 3xx + + x7 + "와 같은 잘못된 입력은 주어지지 않습니다.
- "012x + 001"처럼 0을 제외하고는 0으로 시작하는 수는 없습니다.
- 문자와 숫자 사이의 곱하기는 생략합니다.
- polynomial에는 일차 항과 상수항만 존재합니다.
- 계수 1은 생략합니다.
- 결괏값에 상수항은 마지막에 둡니다.
- 0 < polynomial의 길이 < 50
입출력 예
polynomial result
"3x + 7 + x" | "4x + 7" |
"x + x + x" | "3x" |
정답
class Solution {
public String solution(String polynomial) {
StringBuilder sb = new StringBuilder();
String[] str = polynomial.split(" ");
int xValue = 0;
int value = 0;
for(int i=0; i<str.length; i++) {
if(str[i].contains("x")) {
if(str[i].length()==1) xValue += 1;
else xValue += Integer.parseInt(str[i].substring(0, str[i].length()-1));
}
else if(!str[i].equals("+")) {
value += Integer.parseInt(str[i]);
}
}
if(xValue>1) sb.append(xValue).append("x");
else if(xValue>0) sb.append("x");
if(xValue>0&&value>0) sb.append(" + ");
if(value>0) sb.append(value);
return sb.toString();
}
}
'Problem Solving > Study' 카테고리의 다른 글
[Java] 백준. Study 4주차(BFS, DFS) (0) | 2023.04.12 |
---|---|
[Java] 프로그래머스. Study 3주차(BFS, DFS) (0) | 2023.04.02 |
[Java] 프로그래머스. Study 2주차 (1) | 2023.03.26 |