📑 문1) 첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록 solution 함수를 완성해보세요.
제한사항
입출력 예
numer1 | denom1 | numer2 | denom2 | result |
---|---|---|---|---|
1 | 2 | 3 | 4 | [5,4] |
9 | 2 | 1 | 3 | [29,6] |
입출력 예 설명
1 / 2 + 3 / 4 = 5 / 4입니다. 따라서 [5, 4]를 return 합니다.
9 / 2 + 1 / 3 = 29 / 6입니다. 따라서 [29, 6]을 return 합니다.
나의 풀이
class Solution {
public static int[] solution(int numer1, int denom1, int numer2, int denom2) {
int commonDenominator = denom1 * denom2;
int sumNumerator = (numer1 * denom2) + (numer2 * denom1);
int gcd = findGCD(sumNumerator, commonDenominator);
return new int[] {sumNumerator / gcd, commonDenominator / gcd};
}
public static int findGCD(int a, int b) {
if (b == 0) {
return a;
}
return findGCD(b, a % b);
}
}
나의 생각
기약분수를 구하라
와 같은 문제의 조건이 주어지면 최대공약수
를 이용해서 문제에 접근하면된다. 이번 문제 역시, 분자 sumNumerator
, 분모 commonDenominator
를 구한 뒤, 분자, 분모에 최대공약수를 나눠주면 해결되는 문제였다.
📑 문2) 다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을 모두 위험지역으로 분류합니다.
지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는 지뢰가 매설 된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때, 안전한 지역의 칸 수를 return하도록 solution 함수를 완성해주세요.
제한사항
입출력 예
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 |
입출력 예 설명
(3, 2)에 지뢰가 있으므로 지뢰가 있는 지역과 지뢰와 인접한 위, 아래, 좌, 우, 대각선 총 8칸은 위험지역입니다. 따라서 16을 return합니다.
(3, 2), (3, 3)에 지뢰가 있으므로 지뢰가 있는 지역과 지뢰와 인접한 위, 아래, 좌, 우, 대각선은 위험지역입니다. 따라서 위험지역을 제외한 칸 수 13을 return합니다.
모든 지역에 지뢰가 있으므로 안전지역은 없습니다. 따라서 0을 return합니다.
나의 풀이
class Solution {
public int solution(int[][] board) {
int answer = 0;
int[] dx = {-1, 0, 1, 0, -1, 1, -1, 1};
int[] dy = {0, 1, 0, -1, -1, -1, 1, 1};
int length = board.length;
boolean[][] checkBoard = new boolean[length][length];
for (int i = 0; i < length; i++) {
for (int j = 0; j < length; j++) {
boolean flag = true;
for (int k = 0; k < 8; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (board[i][j] == 1) {
checkBoard[i][j] = true;
}
if (nx >= 0 && nx < length && ny >= 0 && ny < length && board[nx][ny] == 1) {
checkBoard[i][j] = true;
}
}
}
}
for (int i = 0; i < checkBoard.length; i++) {
for (int j = 0; j < checkBoard.length; j++) {
if (!checkBoard[i][j]) {
answer++;
}
}
}
return answer;
}
}
나의 풀이
핵심은 dx
,dy
로 2차원 Grid에서 주변 8개의 셀 ( 북, 동, 남, 서, 북동, 북서, 남동, 남서 )을 탐색하는 방향 벡터이다.
checkBoard
는 board
와 같은 크기의 boolean 타입 2차원 배열로, 초기에는 모든 값이 false
로 설정된다. 특정 조건 ( 지뢰, 지뢰 인근 셀)에 대해 true
값을 설정한다.
첫 번째 중천된 for 반복문은
board
의 모든 셀을 순회한다. 각 셀에 대해,board[i][j]
값이 1이면checkBoard[i][j]
를true
로 설정, 그리고 그 셀 주변 8개의 셀을 살펴보고, 주변 셀의 값이 1이면checkBoard[i][j]
를 true로 설정
두 번째 중첩된 for 반복문은
checkBoard
의 모든 셀을 순회, 만약checkBoard[i][j]
값이false
라면,answer
의 값을 1 증가 시킴
📑 문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 | result |
---|---|
[[0, 1], [2, 5], [3, 9]] | 2 |
[[-1, 1], [1, 3], [3, 9]] | 0 |
[[0, 5], [3, 9], [1, 10]] | 8 |
입출력 예 설명
입출력 예 #1
입출력 예 #2
입출력 예 #3
나의 풀이
첫 시도 (잘못된 풀이)
package programmers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class OverlappingLine {
public static int solution(int[][] lines) {
List<Integer> numbers = new ArrayList<>();
int finalNum = 0;
for(int i = 0; i < lines.length; i++) {
for(int j = lines[i][0]; j< lines[i][1]; j++) {
numbers.add(j);
}
}
System.out.println(numbers);
Set<Integer> set = new LinkedHashSet<>();
Set<Integer> dupNum = new LinkedHashSet<>();
for(Integer number :numbers) {
if(!set.add(number)) {
dupNum.add(number);
}
}
List<Integer> newList = new ArrayList<>();
for(Integer number : dupNum) {
newList.add(number);
}
System.out.println(newList);
Collections.sort(newList);
if(newList.size() == 2){
finalNum = 0;
} else if (newList.size() > 2){
int firstIdx = 0;
int lastIdx = dupNum.size() - 1;
finalNum = newList.get(lastIdx) - newList.get(firstIdx);
}
System.out.println(finalNum);
return finalNum;
}
public static void main(String[] args) {
int[][] lines = {{0,3},{-3,-1},{-2,3}};
solution(lines);
}
}
나의 생각
첫번째 시도
나는 이 문제를 해결하면서 이 문제의 핵심은 중복된 값을 제거하는 것이다
라고 생각하였다. 그래서, Index를 돌며, 각 원소의 시작점과 끝점을 이용하여 for문 반복을 돌려 모든 인덱스의 원소값을 다 추출 하여 set 컬렉션에 넣어, set에 number을 대입하여, 값이 들어가지 않으면 즉, 중복된 값이 존재하면, dupNum에 중복된 값을 넣어주는 방법을 사용하였다.
하지만, 내가 잘못 생각했던 이유는 위와 같은 방법을 사용하면, 중복된 값이 선
이 아닌, 점
도 중복으로 포함시키기 때문에 (겹친 부위가 점으로 존재해도) 예상치 못한 값도 포함될 수 있다.
입출력 예의 테스트는 통과하지만, 제출결과
테스트 케이스 1번, 9번 반례가 존재함을 확인
두번째 시도 (정답)
import java.util.*;
class Solution {
public int solution(int[][] lines) {
int[] rail = new int[201];
for (int[] line : lines) {
for (int j = (line[0] + 100); j < (line[1] + 100); j++) {
rail[j]++;
}
}
int answer = 0;
for (int value : rail) {
if (value > 1) answer++;
}
return answer;
}
}
나의 생각
두번째 시도
풀이법을 순서로 나열해보자.
rail
배열을 선언한다. 각
index
가 특정 위치를 나타내며, 그 위치에 몇 개의 선분이 존재하는지를 나타내는 값이 저장됨
lines
의 2차원 배열을 순회하는데, 각 요소는 [시작점, 끝점]
의 형태를 가지며, 시작점과 끝점은 실제 위치에 100을 더한 값이다. ( 위치가 음수일 수 도 있음을 고려)rail
배열의 해당 index 값을 1씩 증가 시킴
rail
배열은 각 위치에 대해 몇 개의 선분이 겹쳐 있는지를 나타냄
rail
배열을 순회하며, 값이 1보다 큰 경우를 찾음이는 해당 위치에 2개 이상의 선분이 겹쳐 있다는 것을 의미
answer
에 더하고, 이를 반환{{0,5},{3,9},{1,10}}
이 매개변수 lines를 통해 들어오면, 해당 index의 원소값을 +1
해줌
마지막 인덱스를 순회할때 해당 원소값이 중복된 점의 개수가 되고, 그 원소의 값이 1보다 크면 2개 이상의 선분이 겹쳐있다는 것을 의미하게 되므로, 원하는 값을 추출할 수 있음
📑 문4) 점 네 개의 좌표를 담은 이차원 배열 dots가 다음과 같이 매개변수로 주어집니다.
[[x1, y1], [x2, y2], [x3, y3], [x4, y4]]
주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.
제한사항
dots
의 길이 = 4dots
의 원소는 [x,y] 형태이며 x,y는 정수0 ≤ x, y ≤ 100
입출력 예
dots | result |
---|---|
[[1, 4], [9, 2], [3, 8], [11, 6]] | 1 |
[[3, 5], [4, 1], [2, 4], [5, 10]] | 0 |
입출력 예 설명
입출력 예 #1
입출력 예 #2
나의 풀이
package programmers;
public class Parallel {
public static double findSlope(int[] dot1, int[] dot2) {
// 기울기 구하는 공식 : (y2 - y1) / (x2 - x1)
return (double) (dot2[1] - dot1[1]) / (dot2[0] - dot1[0]);
}
public static int solution(int[][] dots) {
int answer = 0;
if (findSlope(dots[0], dots[1]) == findSlope(dots[2], dots[3])) {
return 1;
}
if (findSlope(dots[0], dots[2]) == findSlope(dots[1], dots[3])) {
return 1;
}
if (findSlope(dots[0], dots[3]) == findSlope(dots[1], dots[2])) {
return 1;
}
return answer;
}
public static void main(String[] args) {
int[][] dots = {{3,5},{4,4},{8,9},{6,11}} ;
solution(dots);
}
}
나의 생각
Level 0
막바지에 다가오니 문제가 점점 어려워지는건지, 집중을 잘 못하고 있는듯한 느낌이 많이 들고 있다. 이번 문제에서는 어렵게 생각하면 한 없이 어렵게 , 쉽게 생각하면 한 없이 쉽게 풀 수 있는 문제였던거 같다. 나 역시 반복문을 어떻게 돌려야할까. 어떻게 하면 세련되게 문제를 풀 수 있을지만 생각했지, 쉬운 문제도 마치 어렵게 푸는 그런 마법을 부린듯한 느낌이 들었다. 먼저, findSlope
기울기를 찾는 메서드 부터 보자.
public static double findSlope(int[] dot1, int[] dot2) {
// 기울기 구하는 공식 : (y2 - y1) / (x2 - x1)
return (double) (dot2[1] - dot1[1]) / (dot2[0] - dot1[0]);
}
기울기 : 기울기 구하는 공식 : (y2 - y1) / (x2 - x1)
이다.
public static int solution(int[][] dots) {
int answer = 0;
if (findSlope(dots[0], dots[1]) == findSlope(dots[2], dots[3])) {
return 1;
}
if (findSlope(dots[0], dots[2]) == findSlope(dots[1], dots[3])) {
return 1;
}
if (findSlope(dots[0], dots[3]) == findSlope(dots[1], dots[2])) {
return 1;
}
return answer;
}
{3,5},{4,4},{8,9},{6,11}
의 네점으로 이루어진 2차원 배열이 있다고 할때, 2차원 배열을 원소 하나씩 쪼개어 생각하는 것이다.
findSlope(dots[0], dots[1])
=findSlope({3,5},{4,4})
findSlope(dots[2], dots[3])
=findSlope({8,9}, {6,11})
즉 , index[0]은, index[1], index[2], index[3] 과 (네점을 모두)비교하기 때문에, 모든 조건을 충족할 수 있다. 세 가지의 조건만 비교하면, 문제에서 주어진 제한사항은 자연스레 만족하기 때문에 쉽게 문제를 해결할 수 있다.
📑 문5) 머쓱이는 태어난 지 6개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음을 최대 한 번씩 사용해 조합한(이어 붙인) 발음밖에 하지 못합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.
제한사항
입출력 예
babbing | result |
---|---|
["aya", "yee", "u", "maa", "wyeoo"] | 1 |
["ayaye", "uuuma", "ye", "yemawoo", "ayaa"] | 3 |
입출력 예
입출력 예 #1
입출력 예 #2
유의사항
네 가지를 붙여 만들 수 있는 발음 이외에는 어떤 발음도 할 수 없는 것으로 규정합니다. 예를 들어 "woowo"는 "woo"는 발음할 수 있지만 "wo"를 발음할 수 없기 때문에 할 수 없는 발음입니다.
나의 풀이
package programmers;
import java.util.ArrayList;
public class Babbling {
public static int solution(String[] babbling) {
String[] str = {"aya","ye","woo","ma"};
ArrayList<String> bab = new ArrayList<>();
int cnt = 0;
for(int i = 0; i < babbling.length; i++) {
bab.add(babbling[i]);
for(int j = 0; j < str.length; j++) {
if(bab.get(i).contains(str[j])) {
String replaced = bab.get(i).replace(str[j], " ");
bab.set(i, replaced);
if(bab.get(i).trim().isEmpty()) {
cnt++;
}
}
}
}
return cnt;
}
public static void main(String[] args) {
String[] babbling ={"aya", "yee", "u", "maa", "wyeoo"};
solution(babbling);
}
}
클린 코드로 작성
package programmers;
public class Babbling {
public static int solution(String[] babbling) {
String[] str = {"aya","ye","woo","ma"};
int cnt = 0;
for(int i = 0; i < babbling.length; i++) {
for(String word :str) {
if(babbling[i].contains(word)){
babbling[i] = babbling[i].replace(word, " ");
if(babbling[i].trim().isEmpty()) {
cnt++;
}
}
}
}
return cnt;
}
public static void main(String[] args) {
String[] babbling ={"aya", "yee", "u", "maa", "wyeoo"};
solution(babbling);
}
}
나의 생각
이번 문제는, 불특정한 단어들 속에, 특정 단어가 얼마나 포함됐는가? 를 찾는 문제였다.
예를들어, String[] babbling ={"aya", "yee", "u", "maa", "wyeoo"};
가 있을 때, 아기가 발음 할 수 있는 단어는 String[] str = {"aya","ye","woo","ma"};
불특정한 단어 속에 아기가 발음할 수 있는 단어를 지우고 나면, " ", "e", "u", " a","w oo"
가 된다.
나는 여기서 배열의 isEmpty
메서드를 활용하여 배열이 비어 있으면, cnt를 증가시켜 단어가 모두 포함됐으면 빈 배열로 존재하기 때문에 이를 검출 할 수 있겠다고 생각했다. 하지만 여기에도 문제가 있으니, 과연 " "
를 빈 배열로 인식할 것인가? 테스트를 해봤지만 역시나, 빈 배열로 인식하지 않는다... 이때, 내가 사용한 trim
메서드는 문자열(String)의 양 끝에 있는 공백을 제거하는 역할을 하기 때문에, 빈 배열이 존재하면 ""
로 존재할 것이기 때문에 isEmpty()
메서드로 카운트를 체크할 수 있겠다고 생각
드디어 Level 0
100문제 풀기를 끝냈다. 하루에 한 문제를 꼭 풀자는 마인드로, 혹시 못풀더라도 주말에 푸는 식으로 100문제 풀기를 완료할 수 있었다. 한 걸음씩 앞으로 나아가자! 👍🏻