├── README.md
├── assets
└── java_image.jpg
└── solution
├── 01.java
├── 02.java
├── 03.java
├── 04.java
├── 05.java
├── 06.java
├── 07.java
├── 08.java
├── 09.java
├── 10.java
├── 11.java
├── 12.java
├── 13.java
├── 14.java
├── 15.java
├── 16.java
├── 17.java
├── 18.java
├── 19.java
├── 20.java
├── 21.java
├── 22.java
├── 23.java
├── 24.java
├── 25.java
├── 26.java
├── 27.java
├── 28.java
├── 29.java
├── 30.java
├── 31.java
├── 32.java
├── 33.java
├── 34.java
├── 35.java
├── 36.java
├── 37.java
├── 38.java
├── 39.java
├── 40.java
├── 41.java
├── 42.java
├── 43.java
├── 44.java
├── 45.java
├── 46.java
├── 47.java
├── 48.java
├── 49.java
├── 50.java
├── 51.java
├── 52.java
├── 53.java
├── 54.java
├── 55.java
├── 56.java
├── 57.java
├── 58.java
├── 59.java
├── 60.java
├── 61.java
├── 62.java
├── 63.java
├── 64.java
├── 65.java
├── 66.java
├── 67.java
├── 68.java
├── 69.java
├── 70.java
├── 71.java
├── 72.java
├── 73.java
├── 74.java
├── 75.java
├── 76.java
├── 77.java
├── 78.java
├── 79.java
├── 80.java
├── 81.java
├── 82.java
├── 83.java
├── 84.java
├── 85.java
├── 86.java
├── 87.java
├── 88.java
├── 89.java
├── 90.java
├── 91.java
├── 92.java
├── 93.java
├── 94.java
├── 95.java
├── 96.java
└── 97.java
/README.md:
--------------------------------------------------------------------------------
1 | # 코딩 테스트 합격자 되기(자바 편)
2 | - 프로그래머스에서 엄선한 기출 문제에 대한 상세한 풀이 제공
3 | - 들고 다닐 수 있는 요약 노트 제공
4 | - 실전 문제 위주로 출제된 기출 문제 5회분 제공(회당 3 문제)
5 |
6 |
7 | ## 📖 도서 구매 링크
8 | - Yes24 : https://www.yes24.com/Product/Goods/125183948
9 | - 교보문고 : https://product.kyobobook.co.kr/detail/S000212576322
10 | - 알라딘 : https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=335109613
11 | - 리디북스(Ebook) : https://ridibooks.com/books/4547000036
12 |
13 |
14 |
15 | # 정오표
16 | [클릭](https://docs.google.com/spreadsheets/d/16ZWyC2xlylfsGBdyt2YMT8ogpukNh7sXsHrfx5qQuFk/edit#gid=0)
17 |
18 | # 책소개
19 | 
20 |
21 |
22 | # 진행중인 이벤트
23 | | Event | 세부내용 |기간 |
24 | | ---------- | ---------------------------------------------- |---------------------------------------------- |
25 | |코딩테스트 스터디 |[참여방법 및 스터디 세부사항](https://cafe.naver.com/dremdeveloper/948) | 상시 |
26 |
27 |
28 |
29 | # 코딩테스트 소통공간(저자가 직접운영)
30 | | Title | Description |
31 | | ---------- | ---------------------------------------------- |
32 | |카카오톡 오픈채팅 |[클릭](https://open.kakao.com/o/gQOVhU3f) |
33 |
34 | # 연락처
35 | - 해당 코드들에 대해 문의사항이 있거나, 연락이 필요한 경우 아래 참조
36 |
37 | | Title | Description |
38 | |-------------------|-------------------------------------------------|
39 | | Cafe | http://cafe.naver.com/dremdeveloper |
40 | | Business Mail | kylados@naver.com |
41 | | Codingtest Python | https://github.com/dremdeveloper/codingtest_python |
42 | | Codingtest CPP | https://github.com/dremdeveloper/codingtest_cpp |
43 | # 폴더 구조
44 | - 깃 허브의 폴더 구조에 대한 설명
45 |
46 | | Title | Description |
47 | | ---------- | ---------------------------------------------- |
48 | | errorcode | 구현시 자주 발생하는 에러메시지 |
49 | | mistake | 구현시 자주 실수할수 있는 사항 |
50 | | performance | 비슷한 동작을 하는데 시간복잡도가 다른 경우에 대한 시간비교 |
51 | | reference | 코딩테스트에서 많이 사용하는 문법 |
52 | | solution | 책에 있는 문제에 대한 해설 |
53 | | Algorithm_with_DataStructure | 코딩테스트에 등장하는 알고리즘과 자료구조 |
54 |
--------------------------------------------------------------------------------
/assets/java_image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/retrogemHK/codingtest_java/755a881de4d50479150bcffdee502d98a8503707/assets/java_image.jpg
--------------------------------------------------------------------------------
/solution/01.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(Arrays.toString(solution(new int[]{1, -5, 2, 4, 3})));
7 | System.out.println(Arrays.toString(solution(new int[]{2, 1, 1, 3, 2, 5, 4})));
8 | System.out.println(Arrays.toString(solution(new int[]{6, 1, 7})));
9 | }
10 |
11 | // 이 부분을 변경해서 실행해보세요.
12 | private static int[] solution(int[] arr) {
13 | Arrays.sort(arr);
14 | return arr;
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/solution/02.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 | import java.util.Collections;
3 |
4 | public class Solution {
5 |
6 | public static void main(String[] args) {
7 | System.out.println(Arrays.toString(solution(new int[]{4, 2, 2, 1, 3, 4})));
8 | System.out.println(Arrays.toString(solution(new int[]{2, 1, 1, 3, 2, 5, 4})));
9 | }
10 |
11 | // 이 부분을 변경해서 실행해보세요.
12 | private static int[] solution(int[] arr) {
13 | Integer[] result = Arrays.stream(arr).boxed().distinct().toArray(Integer[]::new); // ❶ 중복값 제거
14 | Arrays.sort(result, Collections.reverseOrder()); // ❷ 내림차순 정렬
15 | return Arrays.stream(result).mapToInt(Integer::intValue).toArray(); // int형 배열로 변경 후 반환
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/solution/03.java:
--------------------------------------------------------------------------------
1 | import java.util.HashSet;
2 |
3 | public class Solution {
4 |
5 | public static int[] solution(int[] numbers) {
6 | HashSet set = new HashSet<>(); // ❶ 중복 값 제거를 위한 해쉬셋 생성
7 | // ❷ 두 수를 선택하는 모든 경우의 수를 반복문으로 구함
8 | for (int i = 0; i < numbers.length - 1; i++) {
9 | for (int j = i + 1; j < numbers.length; j++) {
10 | // ❸ 두 수를 더한 결과를 새로운 배열에 추가
11 | set.add(numbers[i] + numbers[j]);
12 | }
13 | }
14 | // ❹ 해쉬셋의 값을 오름차순 정렬하고 int[] 형태의 배열로 변환하여 반환
15 | return set.stream().sorted().mapToInt(Integer::intValue).toArray();
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/solution/04.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 |
4 | public class Solution {
5 |
6 | public static int[] solution(int[] answers) {
7 | // ❶ 수포자들의 패턴
8 | int[][] pattern = {
9 | {1, 2, 3, 4, 5},
10 | {2, 1, 2, 3, 2, 4, 2, 5},
11 | {3, 3, 1, 1, 2, 2, 4, 4, 5, 5}
12 | };
13 | // ❷ 수포자들의 점수를 저장할 배열
14 | int[] scores = new int[3];
15 |
16 | // ❸ 각 수포자의 패턴과 정답이 얼마나 일치하는지 확인
17 | for (int i = 0; i < answers.length; i++) {
18 | for (int j = 0; j < pattern.length; j++) {
19 | if (answers[i] == pattern[j][i % pattern[j].length]) {
20 | scores[j]++;
21 | }
22 | }
23 | }
24 | // ❹ 가장 높은 점수 저장
25 | int maxScore = Arrays.stream(scores).max().getAsInt();
26 | // ❺ 가장 높은 점수를 가진 수포자들의 번호를 찾아서 리스트에 담음
27 | ArrayList answer = new ArrayList<>();
28 | for (int i = 0; i < scores.length; i++) {
29 | if (scores[i] == maxScore) {
30 | answer.add(i + 1);
31 | }
32 | }
33 |
34 | return answer.stream().mapToInt(Integer::intValue).toArray();
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/solution/05.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int[][] solution(int[][] arr1, int[][] arr2) {
4 | // ❶ 행렬 arr1과 arr2의 행과 열의 수
5 | int r1 = arr1.length;
6 | int c1 = arr1[0].length;
7 | int r2 = arr2.length;
8 | int c2 = arr2[0].length;
9 |
10 | // ❷ 결과를 저장할 2차원 배열 초기화
11 | int[][] answer = new int[r1][c2];
12 |
13 | // ❸ 첫 번째 행렬 arr1의 각 행과 두 번째 행렬 arr2의 각 열에 대해
14 | for (int i = 0; i < r1; i++) {
15 | for (int j = 0; j < c2; j++) {
16 | // ❹ 두 행렬의 데이터를 곱해 결과 리스트에 더해줌
17 | for (int k = 0; k < c1; k++) {
18 | answer[i][j] += arr1[i][k] * arr2[k][j];
19 | }
20 | }
21 | }
22 |
23 | return answer;
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/solution/06.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 |
3 | public class Solution {
4 |
5 | public int[] solution(int N, int[] stages) {
6 | // ❶ 스테이지별 도전자 수를 구함
7 | int[] challenger = new int[N + 2];
8 | for (int i = 0; i < stages.length; i++) {
9 | challenger[stages[i]] += 1;
10 | }
11 |
12 | // ❷ 스테이지별 실패한 사용자 수 계산
13 | HashMap fails = new HashMap<>();
14 | double total = stages.length;
15 |
16 | // ❸ 각 스테이지를 순회하며, 실패율 계산
17 | for (int i = 1; i <= N; i++) {
18 | if (challenger[i] == 0) { // ❹ 도전한 사람이 없는 경우, 실패율은 0
19 | fails.put(i, 0.);
20 | }
21 | else {
22 | fails.put(i, challenger[i] / total); // ❺ 실패율 구함
23 | total -= challenger[i]; // ❻ 다음 스테이지 실패율을 구하기 위해 현재 스테이지의 인원을 뺌
24 | }
25 | }
26 |
27 | // ❼ 실패율이 높은 스테이지부터 내림차순으로 정렬
28 | return fails.entrySet().stream().sorted((o1, o2) -> Double.compare(o2.getValue(), o1.getValue())).mapToInt(HashMap.Entry::getKey).toArray();
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/solution/07.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 | import java.util.HashSet;
3 |
4 | public class Solution {
5 |
6 | // ❶ 좌표평면을 벗어나는지 체크하는 메소드
7 | private static boolean isValidMove(int nx, int ny) {
8 | return 0 <= nx && nx < 11 && 0 <= ny && ny < 11;
9 | }
10 |
11 | // ❷ 다음 좌표 결정을 위한 HashMap 생성
12 | private static final HashMap location = new HashMap<>();
13 |
14 | private static void initLocation() {
15 | location.put('U', new int[]{0, 1});
16 | location.put('D', new int[]{0, -1});
17 | location.put('L', new int[]{-1, 0});
18 | location.put('R', new int[]{1, 0});
19 | }
20 |
21 | public int solution(String dirs) {
22 | initLocation();
23 | int x = 5, y = 5;
24 | HashSet answer = new HashSet<>(); // ❸ 겹치는 좌표는 1개로 처리하기 위함
25 | // ❹ 주어진 명령어로 움직이면서 좌표 저장
26 | for (int i = 0; i < dirs.length(); i++) {
27 | int[] offset = location.get(dirs.charAt(i));
28 | int nx = x + offset[0];
29 | int ny = y + offset[1];
30 | if (!isValidMove(nx, ny)) // ❺ 벗어난 좌표는 인정하지 않음
31 | continue;
32 | // ❻ A에서 B로 간 경우 B에서 A도 추가해야 함(총 경로의 개수는 방향성이 없음)
33 | answer.add(x + " " + y + " " + nx + " " + ny);
34 | answer.add(nx + " " + ny + " " + x + " " + y);
35 | // ❼ 좌표를 이동했으므로 업데이트
36 | x = nx;
37 | y = ny;
38 | }
39 |
40 | return answer.size() / 2;
41 | }
42 |
43 | }
--------------------------------------------------------------------------------
/solution/08.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 |
3 | class Solution {
4 |
5 | private boolean solution(String s) {
6 | ArrayDeque stack = new ArrayDeque<>();
7 |
8 | char[] a = s.toCharArray();
9 | for (char c : a) {
10 | if (c == '(') {
11 | stack.push(c);
12 | }
13 | else {
14 | if(stack.isEmpty() || stack.pop() == c)
15 | return false;
16 | }
17 | }
18 |
19 | return stack.isEmpty();
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/solution/09.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(solution(10));
7 | System.out.println(solution(27));
8 | System.out.println(solution(12345));
9 | }
10 |
11 | // 이 부분을 변경해서 실행해보세요.
12 | public static String solution(int decimal) {
13 | Stack stack = new Stack<>();
14 | while (decimal > 0) {
15 | int remainder = decimal % 2;
16 | stack.push(remainder);
17 | decimal /= 2;
18 | }
19 |
20 | // String 의 + 연산은 시간복잡도 측면에서 성능이 좋지 않습니다.
21 | // 따라서 StringBuilder 를 사용했습니다.
22 | StringBuilder sb = new StringBuilder();
23 | while (!stack.isEmpty()) {
24 | sb.append(stack.pop());
25 | }
26 |
27 | return sb.toString();
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/solution/10.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 | import java.util.HashMap;
3 |
4 | class Solution {
5 |
6 | public static int solution(String s) {
7 | // ❶ 괄호 정보를 저장함. 코드를 간결하게 할 수 있음
8 | HashMap map = new HashMap<>();
9 | map.put(')', '(');
10 | map.put('}', '{');
11 | map.put(']', '[');
12 |
13 | int n = s.length(); // 원본 문자열의 길이 저장
14 | s += s; // 원본 문자열 뒤에 원본 문자열을 이어 붙여서 2번 나오도록 만들어줌
15 |
16 | int answer = 0;
17 |
18 | // ❷ 확인할 문자열의 시작 인덱스를 0 부터 n 까지 이동
19 | A:for (int i = 0; i < n; i++) {
20 | ArrayDeque stack = new ArrayDeque<>();
21 |
22 | // ❸ i(시작 위치)부터 원본 문자열의 길이인 n개까지 올바른 괄호 문자열인지 확인
23 | for (int j = i; j < i + n; j++) {
24 | char c = s.charAt(j);
25 | // HashMap 안에 해당 key 가 없다면 열리는 괄호임
26 | if (!map.containsKey(c)) {
27 | stack.push(c);
28 | }
29 | else {
30 | // ❹ 짝이 맞지 않으면 내부 for문은 종료하고 for문 A로 이동
31 | if(stack.isEmpty() || !stack.pop().equals(map.get(c)))
32 | continue A;
33 | }
34 | }
35 |
36 | // ❺ 3에서 continue 되지 않았고, 스택이 비어있으면 올바른 괄호 문자열임
37 | if (stack.isEmpty())
38 | answer++;
39 | }
40 |
41 | return answer;
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/solution/11.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | public class Solution {
4 |
5 | public int solution(String s) {
6 | Stack stack = new Stack<>();
7 | for (int i = 0; i < s.length(); i++) {
8 | char c = s.charAt(i);
9 | // ❶ 스택이 비어 있지 않고, 현재 문자와 스택의 맨 위 문자가 같으면
10 | if (!stack.isEmpty() && stack.peek() == c) {
11 | stack.pop(); // ❷ 스택의 맨 위 문자 제거
12 | }
13 | else {
14 | stack.push(c); // ❸ 스택에 현재 문자 추가
15 | }
16 | }
17 |
18 | return stack.isEmpty() ? 1 : 0; // ❹ 스택이 비어 있으면 1, 그렇지 않으면 0 반환
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/solution/12.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | class Solution {
4 |
5 | public static int[] solution(int[] prices) {
6 | int n = prices.length;
7 | int[] answer = new int[n]; // ❶ 가격이 떨어지지 않은 기간을 저장할 배열
8 |
9 | // 스택(stack)을 사용해 이전 가격과 현재 가격 비교
10 | Stack stack = new Stack<>(); // ❷ 스택 생성
11 | stack.push(0);
12 |
13 | for (int i = 1; i < n; i++) {
14 | while (!stack.isEmpty() && prices[i] < prices[stack.peek()]) {
15 | // ❸ 가격이 떨어졌으므로 이전 가격의 기간 계산
16 | int j = stack.pop();
17 | answer[j] = i - j;
18 | }
19 | stack.push(i);
20 | }
21 |
22 | // ❹ 스택에 남아 있는 가격들은 가격이 떨어지지 않은 경우
23 | while (!stack.isEmpty()) {
24 | int j = stack.pop();
25 | answer[j] = n - 1 - j;
26 | }
27 |
28 | return answer;
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/solution/13.java:
--------------------------------------------------------------------------------
1 | import java.util.Stack;
2 |
3 | public class Solution {
4 |
5 | public int solution(int[][] board, int[] moves) {
6 | // ❶ 각 열에 대한 스택을 생성합니다.
7 | Stack[] lanes = new Stack[board.length];
8 | for (int i = 0; i < lanes.length; i++) {
9 | lanes[i] = new Stack<>();
10 | }
11 |
12 | // ❷ board를 역순으로 탐색하며, 각 열의 인형을 lanes에 추가합니다.
13 | for (int i = board.length - 1; i >= 0; i--) {
14 | for (int j = 0; j < board[i].length; j++) {
15 | if (board[i][j] > 0) {
16 | lanes[j].push(board[i][j]);
17 | }
18 | }
19 | }
20 |
21 | // ❸ 인형을 담을 bucket을 생성합니다.
22 | Stack bucket = new Stack<>();
23 |
24 | // ❹ 사라진 인형의 총 개수를 저장할 변수를 초기화합니다.
25 | int answer = 0;
26 |
27 | // ❺ moves를 순회하며, 각 열에서 인형을 뽑아 bucket에 추가합니다.
28 | for (int move : moves) {
29 | if (!lanes[move - 1].isEmpty()) { // 해당 열에 인형이 있는 경우
30 | int doll = lanes[move - 1].pop();
31 | // ❻ 바구니에 인형이 있고, 가장 위에 있는 인형과 같은 경우
32 | if (!bucket.isEmpty() && bucket.peek() == doll) {
33 | bucket.pop();
34 | answer += 2;
35 | }
36 | else { // ❼ 바구니에 인형이 없거나, 가장 위에 있는 인형과 다른 경우
37 | bucket.push(doll);
38 | }
39 | }
40 | }
41 |
42 | return answer;
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/solution/14.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 | import java.util.Stack;
3 |
4 | public class Solution {
5 |
6 | public String solution(int n, int k, String[] cmd) {
7 | // ❶ 삭제된 행의 인덱스를 저장하는 스택
8 | Stack deleted = new Stack<>();
9 |
10 | // ❷ 각 행을 기준으로 연산에 따른 위치를 표시하기 위한 배열
11 | int[] up = new int[n + 2];
12 | int[] down = new int[n + 2];
13 |
14 | for (int i = 0; i < n + 2; i++) {
15 | up[i] = i - 1;
16 | down[i] = i + 1;
17 | }
18 |
19 | // ❸ 현재 위치를 나타내는 인덱스
20 | k++;
21 |
22 | // ❹ 주어진 명령어(cmd) 배열을 하나씩 처리
23 | for (String c : cmd) {
24 | // ❺ 현재 위치를 삭제하고 그 다음 위치로 이동
25 | if (c.startsWith("C")) {
26 | deleted.push(k);
27 | up[down[k]] = up[k];
28 | down[up[k]] = down[k];
29 | k = n < down[k] ? up[k] : down[k];
30 | }
31 | // ❻ 가장 최근에 삭제된 행을 복원
32 | else if (c.startsWith("Z")) {
33 | int restore = deleted.pop();
34 | down[up[restore]] = restore;
35 | up[down[restore]] = restore;
36 | }
37 | // ❼ U 또는 D를 사용해 현재 위치를 위아래로 이동
38 | else {
39 | String[] s = c.split(" ");
40 | int x = Integer.parseInt(s[1]);
41 | for (int i = 0; i < x; i++) {
42 | k = s[0].equals("U") ? up[k] : down[k];
43 | }
44 | }
45 | }
46 |
47 | // ❽ 삭제된 행의 위치에 'X'를, 그렇지 않은 행 위치에는 'O'를 저장한 문자열 반환
48 | char[] answer = new char[n];
49 | Arrays.fill(answer, 'O');
50 |
51 | for (int i : deleted) {
52 | answer[i - 1] = 'X';
53 | }
54 |
55 | return new String(answer);
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/solution/15.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(solution(5, 2));
7 | }
8 |
9 | // 이 부분을 변경해서 실행해보세요.
10 | private static int solution(int N, int K) {
11 | // ❶ 1부터 N까지의 번호를 deque에 추가
12 | ArrayDeque deque = new ArrayDeque<>();
13 | for (int i = 1; i <= N; i++) {
14 | deque.addLast(i);
15 | }
16 |
17 | // ❷ deque에 하나의 요소가 남을 때까지 반복
18 | while (deque.size() > 1) {
19 | // ❸ K번째 요소를 찾기 위해 앞에서부터 제거하고 뒤에 추가
20 | for (int i = 0; i < K - 1; i++) {
21 | deque.addLast(deque.pollFirst());
22 | }
23 | deque.pollFirst(); // ❹ K번째 요소 제거
24 | }
25 |
26 | return deque.pollFirst(); // ❺ 마지막으로 남은 요소 반환
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/solution/16.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 | import java.util.Queue;
3 |
4 | public class Solution {
5 |
6 | public int[] solution(int[] progresses, int[] speeds) {
7 | Queue answer = new ArrayDeque<>();
8 |
9 | int n = progresses.length;
10 | // ❶ 각 작업의 배포 가능일 계산
11 | int[] daysLeft = new int[n];
12 | for (int i = 0; i < n; i++) {
13 | daysLeft[i] = (int) Math.ceil((100.0 - progresses[i]) / speeds[i]);
14 | }
15 |
16 | int count = 0; // ❷ 배포될 작접의 수 카운트
17 | int maxDay = daysLeft[0]; // ❸ 현재 배포될 작업 중 가장 늦게 배포될 작업의 가능일
18 |
19 | for (int i = 0; i < n; i++) {
20 | if (daysLeft[i] <= maxDay) { // ❹ 배포 가능일이 가장 늦은 배포일보다 빠르면
21 | count++;
22 | }
23 | else { // ❺ 배포 예정일이 기준 배포일보다 느리면
24 | answer.add(count);
25 | count = 1;
26 | maxDay = daysLeft[i];
27 | }
28 | }
29 |
30 | answer.add(count); // ❻ 마지막으로 카운트된 작업들을 함께 배포
31 | return answer.stream().mapToInt(Integer::intValue).toArray();
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/solution/17.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 | import java.util.Arrays;
3 |
4 | public class Solution {
5 |
6 | public String solution(String[] cards1, String[] cards2, String[] goal) {
7 | // cards와 goal을 deque로 변환
8 | ArrayDeque cardsDeque1 = new ArrayDeque<>(Arrays.asList(cards1));
9 | ArrayDeque cardsDeque2 = new ArrayDeque<>(Arrays.asList(cards2));
10 | ArrayDeque goalDeque = new ArrayDeque<>(Arrays.asList(goal));
11 |
12 | // ❶ goalDeque에 문자열이 남아있으면 계속 반복
13 | while (!goalDeque.isEmpty()) {
14 | // ❷ cardsDeque1의 front와 일치하는 경우
15 | if (!cardsDeque1.isEmpty() && cardsDeque1.peekFirst().equals(goalDeque.peekFirst())) {
16 | cardsDeque1.pollFirst();
17 | goalDeque.pollFirst();
18 | }
19 | // ❸ cardsDeque2의 front와 일치하는 경우
20 | else if (!cardsDeque2.isEmpty() && cardsDeque2.peekFirst().equals(goalDeque.peekFirst())) {
21 | cardsDeque2.pollFirst();
22 | goalDeque.pollFirst();
23 | }
24 | else {
25 | break; // 일치하는 원소를 찾지 못했으므로 종료
26 | }
27 | }
28 |
29 | // ❹ goal이 비었으면 "Yes" 아니면 "No"를 반환
30 | return goalDeque.isEmpty() ? "Yes" : "No";
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/solution/18.java:
--------------------------------------------------------------------------------
1 | import java.util.HashSet;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(solution(new int[]{1, 2, 3, 4, 8}, 6));
7 | System.out.println(solution(new int[]{2, 3, 5, 9}, 10));
8 | }
9 |
10 | // 이 부분을 변경해서 실행해보세요.
11 | private static boolean solution(int[] arr, int target) {
12 | HashSet hashSet = new HashSet<>();
13 |
14 | for (int i : arr) {
15 | // ❶ target에서 현재 원소를 뺀 값이 hashSet에 있는지 확인
16 | if (hashSet.contains(target - i)) {
17 | return true;
18 | }
19 |
20 | // ❷ hashSet에 현재 값 저장
21 | hashSet.add(i);
22 | }
23 |
24 | return false;
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/solution/19.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 |
3 | public class Solution {
4 |
5 | public String solution(String[] participant, String[] completion) {
6 | // ❶ 해시맵 생성
7 | HashMap hashMap = new HashMap<>();
8 | // ❷ 완주한 선수들의 이름을 해시맵에 저장
9 | for (String string : completion) {
10 | hashMap.put(string, hashMap.getOrDefault(string, 0) + 1);
11 | }
12 |
13 | // ❸ 참가한 선수들의 이름을 키로 하는 값을 1씩 감소
14 | for (String string : participant) {
15 | // ❹ 완주하지 못한 선수를 찾으면 반환
16 | if (hashMap.getOrDefault(string, 0) == 0) {
17 | return string;
18 | }
19 | hashMap.put(string, hashMap.get(string) - 1);
20 | }
21 |
22 | return null;
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/solution/20.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 |
3 | public class Solution {
4 |
5 | public int solution(String[] want, int[] number, String[] discount) {
6 | // ❶ want, number배열의 값을 해시맵에 저장
7 | HashMap wantMap = new HashMap<>();
8 | for (int i = 0; i < want.length; i++) {
9 | wantMap.put(want[i], number[i]);
10 | }
11 |
12 | int answer = 0; // ❷ 총 일수를 계산할 변수 초기화
13 |
14 | // ❸ 특정일 i에 회원가입 시 할인받을 수 있는 품목 체크
15 | for (int i = 0; i < discount.length - 9; i++) {
16 | // ❹ i일 회원가입 시 할인받는 제품 및 개수를 담을 해시맵
17 | HashMap discount10d = new HashMap<>();
18 |
19 | // ❺ i일 회원가입 시 할인받는 제품 및 개수로 해시맵 구성
20 | for (int j = i; j < i + 10; j++) {
21 | if (wantMap.containsKey(discount[j])) {
22 | discount10d.put(discount[j], discount10d.getOrDefault(discount[j], 0) + 1);
23 | }
24 | }
25 |
26 | // ❻ 할인하는 상품의 개수가 원하는 수량과 일치하면 정답 변수에 1 추가
27 | if (discount10d.equals(wantMap))
28 | answer++;
29 | }
30 |
31 |
32 | return answer;
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/solution/21.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.HashMap;
3 |
4 | public class Solution {
5 |
6 | private String[] solution(String[] record) {
7 | // Enter/Leave 메세지를 저장할 해시맵 생성
8 | HashMap msg = new HashMap<>();
9 | msg.put("Enter", "님이 들어왔습니다.");
10 | msg.put("Leave", "님이 나갔습니다.");
11 |
12 | HashMap uid = new HashMap<>();
13 |
14 | // ❶ record의 각 줄을 하나씩 처리
15 | for (String s : record) {
16 | String[] cmd = s.split(" ");
17 | if (cmd.length == 3) { // ❷ Enter 또는 Change인 경우
18 | uid.put(cmd[1], cmd[2]);
19 | }
20 | }
21 |
22 | // 답을 저장할 answer List 생성
23 | ArrayList answer = new ArrayList<>();
24 |
25 | // ❸ record의 각 줄을 하나씩 처리
26 | for (String s : record) {
27 | String[] cmd = s.split(" ");
28 | // ❹ 각 상태에 맞는 메세지를 answer에 저장
29 | if (msg.containsKey(cmd[0])) {
30 | answer.add(uid.get(cmd[1]) + msg.get(cmd[0]));
31 | }
32 | }
33 |
34 | return answer.toArray(new String[0]);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/solution/22.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.HashMap;
3 | import java.util.Map;
4 | import java.util.stream.Stream;
5 |
6 | public class Solution {
7 |
8 | public int[] solution(String[] genres, int[] plays) {
9 | HashMap> genreMap = new HashMap<>();
10 | HashMap playMap = new HashMap<>();
11 |
12 | // ❶ 장르별 총 재생 횟수와 각 곡의 재생 횟수 저장
13 | for (int i = 0; i < genres.length; i++) {
14 | String genre = genres[i];
15 | int play = plays[i];
16 | if (!genreMap.containsKey(genre)) {
17 | genreMap.put(genre, new ArrayList<>());
18 | playMap.put(genre, 0);
19 | }
20 | genreMap.get(genre).add(new int[]{i, play});
21 | playMap.put(genre, playMap.get(genre) + play);
22 | }
23 |
24 | ArrayList answer = new ArrayList<>();
25 |
26 | // ❷ 총 재생 횟수가 많은 장르순으로 내림차순 정렬
27 | Stream> sortedGenre = playMap.entrySet()
28 | .stream()
29 | .sorted((o1, o2) -> Integer.compare(o2.getValue(), o1.getValue()));
30 |
31 | // ❸ 각 장르 내에서 노래를 재생 횟수 순으로 정렬해 최대 2곡까지 선택
32 | sortedGenre.forEach(entry -> {
33 | Stream sortedSongs = genreMap.get(entry.getKey()).stream()
34 | .sorted((o1, o2) -> Integer.compare(o2[1], o1[1]))
35 | .limit(2);
36 | sortedSongs.forEach(song -> answer.add(song[0]));
37 | });
38 |
39 | return answer.stream().mapToInt(Integer::intValue).toArray();
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/solution/23.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 | import java.util.HashSet;
3 | import java.util.Map;
4 |
5 | public class Solution {
6 |
7 | public int[] solution(String[] id_list, String[] report, int k) {
8 | // 신고당한 유저 - 신고 유저 집합을 저장할 해시맵
9 | HashMap> reportedUser = new HashMap<>();
10 | // 처리 결과 메일을 받은 유저 - 받은 횟수를 저장할 해시맵
11 | HashMap count = new HashMap<>();
12 |
13 | // ❶ 신고 기록 순회
14 | for (String r : report) {
15 | String[] s = r.split(" ");
16 | String userId = s[0];
17 | String reportedId = s[1];
18 |
19 | if (!reportedUser.containsKey(reportedId)) { // ❷ 신고당한 기록이 없다면
20 | reportedUser.put(reportedId, new HashSet<>());
21 | }
22 | // ❸ 신고한 사람의 아이디를 해시맵의 value인 해시셋에 추가
23 | reportedUser.get(reportedId).add(userId);
24 | }
25 |
26 | for (Map.Entry> entry : reportedUser.entrySet()) {
27 | if (entry.getValue().size() >= k) { // ❹ 정지 기준에 만족하는지 확인
28 | for (String uid : entry.getValue()) { // ❺ 해시셋을 순회하며 count 계산
29 | count.put(uid, count.getOrDefault(uid, 0) + 1);
30 | }
31 | }
32 | }
33 |
34 | int[] answer = new int[id_list.length];
35 |
36 | // ❻ 각 아이디별 메일을 받은 횟수를 순서대로 정리
37 | for (int i = 0; i < id_list.length; i++) {
38 | answer[i] = count.getOrDefault(id_list[i], 0);
39 | }
40 |
41 | return answer;
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/solution/24.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | public class Solution {
4 |
5 | // 만들 수 있는 메뉴 구성과 총 주문 수를 저장할 해시맵
6 | private static HashMap> courseMap;
7 |
8 | public String[] solution(String[] orders, int[] course) {
9 | // 해시맵 초기화
10 | courseMap = new HashMap<>();
11 | for (int i : course) {
12 | courseMap.put(i, new HashMap<>());
13 | }
14 |
15 | // ❶ 코스를 배열로 만들고 오름차순 정렬해서 가능한 모든 메뉴 구성을 구함
16 | for (String order : orders) {
17 | char[] orderArray = order.toCharArray();
18 | Arrays.sort(orderArray);
19 | combinations(0, orderArray, "");
20 | }
21 |
22 | ArrayList answer = new ArrayList<>();
23 |
24 | // ❷ 모든 코스 후보에 대해서
25 | for (HashMap count : courseMap.values()) {
26 | count.values()
27 | .stream()
28 | .max(Comparator.comparingInt(o -> o)) // ❸ 가장 빈도수가 높은 코스를 찾음
29 | .ifPresent(cnt -> count.entrySet() // ❹ 코스에 대한 메뉴 수가 가능할 때만
30 | .stream()
31 | // ❺ 최소 2명 이상의 손님으로부터 주문된 단품메뉴 조합에 대해서만
32 | .filter(entry -> cnt.equals(entry.getValue()) && cnt > 1)
33 | // ❻ 코스 메뉴만 answer 리스트에 추가
34 | .forEach(entry -> answer.add(entry.getKey())));
35 | }
36 |
37 | Collections.sort(answer); // ❼ 오름차순으로 정렬
38 | return answer.toArray(new String[0]);
39 | }
40 |
41 | // 만들 수 있는 모든 조합을 재귀 함수를 이용해서 구현
42 | public static void combinations(int idx, char[] order, String result) {
43 | // 필요한 코스 메뉴의 수와 일치하는 것만 저장
44 | if (courseMap.containsKey(result.length())) {
45 | HashMap map = courseMap.get(result.length());
46 | // 해당 코스의 수를 1증가
47 | map.put(result, map.getOrDefault(result, 0) + 1);
48 | }
49 |
50 | for (int i = idx; i < order.length; i++) {
51 | combinations(i + 1, order, result + order[i]);
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/solution/25.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | int[] input = {1, 2, 3, 4, 5, 6, 7};
7 | System.out.println(Arrays.toString(solution(input)));
8 | }
9 |
10 | // 이 부분을 변경해서 실행해보세요.
11 | public static String[] solution(int[] nodes) {
12 | String[] result = new String[3];
13 | result[0] = preorder(nodes, 0).trim(); // 마지막 공백 제거
14 | result[1] = inorder(nodes, 0).trim(); // 마지막 공백 제거
15 | result[2] = postorder(nodes, 0).trim(); // 마지막 공백 제거
16 | return result;
17 | }
18 |
19 | private static String preorder(int[] nodes, int idx) {
20 | if (idx >= nodes.length) { // idx가 범위를 벗어나면 빈 문자열 반환
21 | return "";
22 | }
23 |
24 | // 루트 노드 -> 왼쪽 서브 트리 -> 오른쪽 서브 트리 순으로 재귀 호출하여 결과를 이어붙임
25 | return nodes[idx] + " " +
26 | preorder(nodes, 2 * idx + 1) +
27 | preorder(nodes, 2 * idx + 2);
28 | }
29 |
30 | private static String inorder(int[] nodes, int idx) {
31 | if (idx >= nodes.length) { // idx가 범위를 벗어나면 빈 문자열 반환
32 | return "";
33 | }
34 |
35 | // 왼쪽 서브 트리 -> 루트 노드 -> 오른쪽 서브 트리 순으로 재귀 호출하여 결과를 이어붙임
36 | return inorder(nodes, 2 * idx + 1) +
37 | nodes[idx] + " " +
38 | inorder(nodes, 2 * idx + 2);
39 | }
40 |
41 | private static String postorder(int[] nodes, int idx) {
42 | if (idx >= nodes.length) { // idx가 범위를 벗어나면 빈 문자열 반환
43 | return "";
44 | }
45 |
46 | // 왼쪽 서브 트리 -> 오른쪽 서브 트리 -> 루트 노드 순으로 재귀 호출하여 결과를 이어붙임
47 | return postorder(nodes, 2 * idx + 1) +
48 | postorder(nodes, 2 * idx + 2) +
49 | nodes[idx] + " ";
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/solution/26.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int n, int a, int b) {
4 | int answer;
5 |
6 | for(answer = 0; a != b; answer++) {
7 | a = (a + 1) / 2;
8 | b = (b + 1) / 2;
9 | }
10 |
11 | return answer;
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/solution/27.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 |
3 | public class Solution {
4 |
5 | public int[] solution(String[] enroll, String[] referral, String[] seller, int[] amount) {
6 | // ❶ parent 해시맵. key는 enroll의 노드, value는 referral의 노드로 구성됨
7 | HashMap parent = new HashMap<>();
8 | for (int i = 0; i < enroll.length; i++) {
9 | parent.put(enroll[i], referral[i]);
10 | }
11 |
12 | // ❷ total 해시맵 생성
13 | HashMap total = new HashMap<>();
14 |
15 | // ❸ seller 배열과 amount 배열을 이용하여 이익 분배
16 | for (int i = 0; i < seller.length; i++) {
17 | String curName = seller[i];
18 | // ❹ 판매자가 판매한 총 금액 계산
19 | int money = amount[i] * 100;
20 | // ❺ 판매자부터 차례대로 상위 노드로 이동하며 이익 분배
21 | while (money > 0 && !curName.equals("-")) {
22 | // ❻ 현재 판매자가 받을 금액 계산(10%를 제외한 금액)
23 | total.put(curName, total.getOrDefault(curName, 0) + money - (money / 10));
24 | curName = parent.get(curName);
25 | // ❼ 10% 를 제외한 금액 계산
26 | money /= 10;
27 | }
28 | }
29 |
30 | // ❽ enroll 배열의 모든 노드에 대해 해당하는 이익을 배열로 반환
31 | int[] answer = new int[enroll.length];
32 | for (int i = 0; i < enroll.length; i++) {
33 | answer[i] = total.getOrDefault(enroll[i], 0);
34 | }
35 | return answer;
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/solution/28.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 | import java.util.ArrayList;
3 | import java.util.HashSet;
4 |
5 | public class Solution {
6 |
7 | // 현재 위치, 양의 수, 늑대의 수 방문한 노드 저장을 위한 클래스
8 | private static class Info {
9 | int node, sheep, wolf;
10 | HashSet visited;
11 |
12 | public Info(int node, int sheep, int wolf, HashSet visited) {
13 | this.node = node;
14 | this.sheep = sheep;
15 | this.wolf = wolf;
16 | this.visited = visited;
17 | }
18 | }
19 |
20 | private static ArrayList[] tree; // 트리 정보를 저장할 인접리스트
21 |
22 | // ❶ 트리 구축 메소드
23 | private static void buildTree(int[] info, int[][] edges) {
24 | tree = new ArrayList[info.length];
25 | for (int i = 0; i < tree.length; i++) {
26 | tree[i] = new ArrayList<>();
27 | }
28 |
29 | for (int[] edge : edges) {
30 | tree[edge[0]].add(edge[1]);
31 | }
32 | }
33 |
34 | public int solution(int[] info, int[][] edges) {
35 | buildTree(info, edges); // ❷ 트리 생성
36 |
37 | int answer = 0; // ❸ 최대 양의 수를 저장할 변수
38 |
39 | // ❹ BFS를 위한 큐 생성 및 초기 상태 설정
40 | ArrayDeque queue = new ArrayDeque<>();
41 | queue.add(new Info(0, 1, 0, new HashSet<>()));
42 |
43 | // BFS(너비 우선 탐색) 시작
44 | while (!queue.isEmpty()) {
45 | // ❺ 큐에서 현재 상태를 꺼냄
46 | Info now = queue.poll();
47 | // ❻ 최대 양의 수 업데이트
48 | answer = Math.max(answer, now.sheep);
49 | // ❼ 방문한 노드 집합에 현재 노드의 이웃 노드 추가
50 | now.visited.addAll(tree[now.node]);
51 |
52 | // ❽ 인접한 노드들에 대해 탐색
53 | for (int next : now.visited) {
54 | // ❾ 기존 해시셋의 데이터를 복사하고 현재 방문한 정점을 해시셋에서 제거
55 | HashSet set = new HashSet<>(now.visited);
56 | set.remove(next);
57 |
58 | if (info[next] == 1) { // ➓ 늑대일 경우
59 | if (now.sheep != now.wolf + 1) {
60 | queue.add(new Info(next, now.sheep, now.wolf + 1, set));
61 | }
62 | }
63 | else { // ⓫ 양일 경우
64 | queue.add(new Info(next, now.sheep + 1, now.wolf, set));
65 | }
66 | }
67 | }
68 |
69 | return answer;
70 | }
71 |
72 | }
--------------------------------------------------------------------------------
/solution/29.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 |
4 | public class Code324A_길찾기게임 {
5 |
6 | // ❶ Node 클래스 정의
7 | private static class Node {
8 | int x, y, num; // 노드의 좌표, 번호 저장
9 | Node left, right; // 노드의 왼쪽, 오른쪽 자식 노드
10 |
11 | public Node(int num, int x, int y) {
12 | this.num = num;
13 | this.x = x;
14 | this.y = y;
15 | }
16 | }
17 |
18 | // ❷ 이진 트리 생성 메소드
19 | private static Node makeBT(int[][] nodeinfo) {
20 | // ❸ 각 노드에 대한 좌표, 번호를 배열에 저장
21 | Node[] nodes = new Node[nodeinfo.length];
22 | for (int i = 0; i < nodeinfo.length; i++) {
23 | nodes[i] = new Node(i + 1, nodeinfo[i][0], nodeinfo[i][1]);
24 | }
25 |
26 | // ❹ y 기준으로 내림차순 정렬, y가 같다면 x를 기준으로 오름차순 정렬
27 | Arrays.sort(nodes, (o1, o2) -> {
28 | if (o1.y == o2.y)
29 | return Integer.compare(o1.x, o2.x);
30 | return Integer.compare(o2.y, o1.y);
31 | });
32 |
33 | Node root = nodes[0]; // 맨 처음 노드는 무조건 루트
34 |
35 | for (int i = 1; i < nodes.length; i++) {
36 | Node parent = root;
37 | while (true) {
38 | // ❺ 부모 노드의 x좌표가 더 크면 왼쪽으로
39 | if (nodes[i].x < parent.x) {
40 | if (parent.left == null) {
41 | parent.left = nodes[i];
42 | break;
43 | }
44 | else {
45 | parent = parent.left;
46 | }
47 | }
48 | // ❻ 부모 노드의 x좌표가 더 작거나 같으면 오른쪽으로
49 | else {
50 | if (parent.right == null) {
51 | parent.right = nodes[i];
52 | break;
53 | }
54 | else {
55 | parent = parent.right;
56 | }
57 | }
58 | }
59 | }
60 |
61 | return nodes[0];
62 | }
63 |
64 | // ❼ 전위 순회 메소드
65 | private static void preOrder(Node curr, ArrayList answer) {
66 | if (curr == null) {
67 | return;
68 | }
69 | answer.add(curr.num);
70 | preOrder(curr.left, answer);
71 | preOrder(curr.right, answer);
72 | }
73 |
74 | // ❽ 후위 순회 메소드
75 | private static void postOrder(Node curr, ArrayList answer) {
76 | if (curr == null) {
77 | return;
78 | }
79 | postOrder(curr.left, answer);
80 | postOrder(curr.right, answer);
81 | answer.add(curr.num);
82 | }
83 |
84 | public int[][] solution(int[][] nodeinfo) {
85 | Node root = makeBT(nodeinfo); // 이진트리 생성
86 |
87 | ArrayList preOrderList = new ArrayList<>();
88 | preOrder(root, preOrderList); // 전위 순회
89 | ArrayList postOrderList = new ArrayList<>();
90 | postOrder(root, postOrderList); // 후위 순회
91 |
92 | // 결과 반환
93 | int[][] answer = new int[2][nodeinfo.length];
94 | answer[0] = preOrderList.stream().mapToInt(Integer::intValue).toArray();
95 | answer[1] = postOrderList.stream().mapToInt(Integer::intValue).toArray();
96 |
97 | return answer;
98 | }
99 |
100 | }
--------------------------------------------------------------------------------
/solution/30.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 |
4 | public class Solution {
5 |
6 | public static void main(String[] args) {
7 | int[][] operations1 = {{0, 0, 1}, {0, 1, 2}, {1, 1, 2}};
8 | System.out.println(Arrays.toString(solution(3, operations1)));
9 | int[][] operations2 = {{0, 0, 1}, {1, 1, 2}, {0, 1, 2}, {1, 0, 2}};
10 | System.out.println(Arrays.toString(solution(3, operations2)));
11 | }
12 |
13 | // 부모 저장을 위한 배열
14 | private static int[] parent;
15 |
16 | // 루트 노드를 찾는 메소드
17 | private static int find(int x) {
18 | // 만약 x의 부모가 자기 자신이면, 즉 x가 루트 노드라면 x를 반환
19 | if (parent[x] == x)
20 | return x;
21 | // 그렇지 않다면 x의 부모를 찾아서 parent[x]에 저장합니다.
22 | parent[x] = find(parent[x]);
23 | return parent[x]; // 찾은 루트 노드를 반환
24 | }
25 |
26 | private static void union(int x, int y) {
27 | int root1 = find(x); // x가 속한 집합의 루트 노드 찾기
28 | int root2 = find(y); // y가 속한 집합의 루트 노드 찾기
29 |
30 | parent[root2] = root1; // y가 속한 집합을 x가 속한 집합에 합침
31 | }
32 |
33 | // 이 부분을 변경해서 실행해보세요.
34 | private static Boolean[] solution(int k, int[][] operation) {
35 | // 노드의 수 만큼 배열 생성
36 | parent = new int[k];
37 | // 처음에는 각 노드가 자기 자신을 부모로 가지도록 초기화
38 | for (int i = 0; i < k; i++) {
39 | parent[i] = i;
40 | }
41 |
42 | ArrayList answer = new ArrayList<>();
43 |
44 | for (int[] op : operation) {
45 | if (op[0] == 0) { // 0 연산이면
46 | union(op[1], op[2]);
47 | }
48 | else { // 1 연산이면
49 | answer.add(find(op[1]) == find(op[2]));
50 | }
51 | }
52 |
53 | return answer.toArray(new Boolean[0]);
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/solution/31.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 | import java.util.HashSet;
3 | import java.util.stream.Collectors;
4 |
5 | public class Solution {
6 |
7 | public int solution(int[] nums) {
8 | // ❶ nums 리스트에서 중복을 제거한 집합(set)을 구함
9 | HashSet set = Arrays.stream(nums).boxed().collect(Collectors.toCollection(HashSet::new));
10 | // ❷ 폰켓몬의 총 수
11 | int n = nums.length;
12 | // ❸ 선택할 폰켓몬의 수
13 | int k = n / 2;
14 | // ❹ 중복을 제거한 폰켓몬의 종류 수와 선택할 폰켓몬의 수 중 작은 값 반환
15 | return Math.min(k, set.size());
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/solution/32.java:
--------------------------------------------------------------------------------
1 | import java.util.HashSet;
2 |
3 | public class Solution {
4 |
5 | public int[] solution(int n, String[] words) {
6 | // ❶ 이미 사용한 단어를 저장하는 set
7 | HashSet usedWords = new HashSet<>();
8 | // ❷ 이전 단어의 마지막 글자
9 | char prevWord = words[0].charAt(0);
10 |
11 | for (int i = 0; i < words.length; i++) {
12 | // ❸ 이미 사용한 단어이거나 첫 글자가 이전 단어와 일치하지 않으면
13 | if (usedWords.contains(words[i]) || words[i].charAt(0) != prevWord) {
14 | // ❹ 탈락하는 사람의 번호와 차례를 반환
15 | return new int[]{(i % n) + 1, (i / n) + 1};
16 | }
17 | // ❺ 사용한 단어로 추가
18 | usedWords.add(words[i]);
19 | // ❻ 이전 단어의 마지막 글자 업데이트
20 | prevWord = words[i].charAt(words[i].length() - 1);
21 | }
22 |
23 | // ❼ 모두 통과했을 경우 반환값
24 | return new int[]{0, 0};
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/solution/33.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | private static int[] parent;
6 |
7 | private static int find(int x) {
8 | // ❶ x가 속한 집합의 루트 노드 찾기
9 | if (parent[x] == x)
10 | return x;
11 | // ❷ 경로 압축: x의 부모를 루트로 설정
12 | return parent[x] = find(parent[x]);
13 | }
14 |
15 | private static void union(int x, int y) {
16 | // ❸ 두 집합을 하나의 집합으로 합치기
17 | int root1 = find(x);
18 | int root2 = find(y);
19 | parent[root2] = root1;
20 | }
21 |
22 | public int solution(int n, int[][] costs) {
23 | // ❹ 비용을 기준으로 다리를 오름차순 정렬
24 | Arrays.sort(costs, (o1, o2) -> Integer.compare(o1[2], o2[2]));
25 |
26 | // ❺ parent 배열 초기화
27 | parent = new int[n];
28 | for (int i = 0; i < n; i++) {
29 | parent[i] = i;
30 | }
31 |
32 | int answer = 0; // 최소 신장 트리의 총 비용
33 | int edges = 0; // 연결된 다리의 수
34 |
35 | for (int[] edge : costs) {
36 | // ❻ n - 1개의 다리가 연결된 경우 모든 섬이 연결됨
37 | if (edges == n - 1)
38 | break;
39 |
40 | // ❼ 현재 다리가 연결하는 두 섬이 이미 연결되어 있는지 확인
41 | if (find(edge[0]) != find(edge[1])) {
42 | // ❽ 두 섬을 하나의 집합으로 연결함
43 | union(edge[0], edge[1]);
44 | // ❾ 현재 다리의 건설 비용을 비용에 추가
45 | answer += edge[2];
46 | // ➓ 사용된 다리의 수 1증가
47 | edges++;
48 | }
49 | }
50 |
51 | return answer;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/solution/34.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 |
4 | public class Solution {
5 |
6 | public static void main(String[] args) {
7 | int[][] graph1 = {{1, 2}, {2, 3}, {3, 4}, {4, 5}};
8 | System.out.println(Arrays.toString(solution(graph1, 1, 5)));
9 | int[][] graph2 = {{1, 2}, {1, 3}, {2, 4}, {2, 5}, {3, 6}, {5, 6}};
10 | System.out.println(Arrays.toString(solution(graph2, 1, 6)));
11 | }
12 |
13 | // 인접 리스트 저장할 ArrayList 배열
14 | private static ArrayList[] adjList;
15 |
16 | // 방문 여부를 저장할 boolean 배열
17 | private static boolean[] visited;
18 |
19 | private static ArrayList answer;
20 |
21 | // 이 부분을 변경해서 실행해보세요.
22 | private static int[] solution(int[][] graph, int start, int n) {
23 | // ❶ 인접 리스트 초기화
24 | adjList = new ArrayList[n + 1];
25 | for (int i = 0; i < adjList.length; i++) {
26 | adjList[i] = new ArrayList<>();
27 | }
28 |
29 | // ❷ 그래프를 인접 리스트로 변환
30 | for (int[] edge : graph) {
31 | adjList[edge[0]].add(edge[1]);
32 | }
33 |
34 | // DFS를 순회한 결과를 반환
35 | visited = new boolean[n + 1];
36 | answer = new ArrayList<>();
37 | dfs(start); // ❼ 시작 노드에서 깊이 우선 탐색 시작
38 |
39 | // ❽ DFS 탐색 결과 반환
40 | return answer.stream().mapToInt(Integer::intValue).toArray();
41 | }
42 |
43 | // ❸ DFS 탐색 메소드
44 | private static void dfs(int now) {
45 | visited[now] = true; // ❹ 현재 노드를 방문했음을 저장
46 | answer.add(now); // ❺ 현재 노드를 결과 리스트에 추가
47 | // ❻ 현재 노드와 인접한 노드 순회
48 | for (int next : adjList[now]) {
49 | if (!visited[next]) {
50 | dfs(next);
51 | }
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/solution/35.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 | import java.util.ArrayList;
3 | import java.util.Arrays;
4 |
5 | public class Solution {
6 |
7 | public static void main(String[] args) {
8 | int[][] graph1 = {{1, 2}, {1, 3}, {2, 4}, {2, 5}, {3, 6}, {3, 7}, {4, 8}, {5, 8}, {6, 9}, {7, 9}};
9 | System.out.println(Arrays.toString(solution(graph1, 1, 9)));
10 | int[][] graph2 = {{1, 3}, {3, 4}, {3, 5}, {5, 2}};
11 | System.out.println(Arrays.toString(solution(graph2, 1, 5)));
12 | }
13 |
14 | // 인접 리스트 저장할 ArrayList 배열
15 | private static ArrayList[] adjList;
16 |
17 | // 방문 여부를 저장할 boolean 배열
18 | private static boolean[] visited;
19 |
20 | private static ArrayList answer;
21 |
22 | // 이 부분을 변경해서 실행해보세요.
23 | private static int[] solution(int[][] graph, int start, int n) {
24 | adjList = new ArrayList[n + 1];
25 | for (int i = 0; i < adjList.length; i++) {
26 | adjList[i] = new ArrayList<>();
27 | }
28 |
29 | for (int[] edge : graph) {
30 | adjList[edge[0]].add(edge[1]);
31 | }
32 |
33 | // ❶ 방문 여부를 저장할 배열
34 | visited = new boolean[n + 1];
35 | answer = new ArrayList<>();
36 | bfs(start); // ❽ 시작 노드에서 너비 우선 탐색 시작
37 |
38 | return answer.stream().mapToInt(Integer::intValue).toArray();
39 | }
40 |
41 | // BFS 탐색 메소드
42 | private static void bfs(int start) {
43 | // ❷ 탐색시 맨 처음 방문할 노드를 add 하고 방문처리
44 | ArrayDeque queue = new ArrayDeque<>();
45 | queue.add(start);
46 | visited[start] = true;
47 |
48 | // ❸ 큐가 비어 있지 않은 동안 반복
49 | while (!queue.isEmpty()) {
50 | // ❹ 큐에 있는 원소 중 가장 먼저 추가된 원소를 poll하고 정답 리스트에 추가
51 | int now = queue.poll();
52 | answer.add(now);
53 | // ❺ 인접한 이웃 노드들에 대해서
54 | for (int next : adjList[now]) {
55 | if (!visited[next]) { // ❻ 방문하지 않은 인접한 노드인 경우
56 | // ❼ 인접한 노드를 방문 처리함
57 | queue.add(next);
58 | visited[next] = true;
59 | }
60 | }
61 | }
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/solution/36.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 | import java.util.PriorityQueue;
4 |
5 | public class Solution {
6 |
7 | public static void main(String[] args) {
8 | int[][] graph = {{0, 1, 9}, {0, 2, 3}, {1, 0, 5}, {2, 1, 1}};
9 | System.out.println(Arrays.toString(solution(graph, 0, 3)));
10 | int[][] graph2 = {{0, 1, 1}, {1, 2, 5}, {2, 3, 1}};
11 | System.out.println(Arrays.toString(solution(graph2, 0, 4)));
12 | }
13 |
14 | // 노드의 정보(노드 번호와 거리)를 쌍으로 저장할 클래스 생성
15 | private static class Node {
16 | int dest, cost;
17 |
18 | public Node(int dest, int cost) {
19 | this.dest = dest;
20 | this.cost = cost;
21 | }
22 | }
23 |
24 | // 이 부분을 변경해서 실행해보세요.
25 | public static int[] solution(int[][] graph, int start, int n) {
26 | // ❶ 인접 리스트를 저장할 ArrayList 배열 초기화
27 | ArrayList[] adjList = new ArrayList[n];
28 | for (int i = 0; i < n; i++) {
29 | adjList[i] = new ArrayList<>();
30 | }
31 |
32 | // ❷ graph 정보를 인접 리스트로 저장
33 | for (int[] edge : graph) {
34 | adjList[edge[0]].add(new Node(edge[1], edge[2]));
35 | }
36 |
37 | int[] dist = new int[n];
38 | // ❸ 모든 노드의 거리 값을 무한대로 초기화
39 | Arrays.fill(dist, Integer.MAX_VALUE);
40 |
41 | // ❹ 시작 노드의 거리 값은 0으로 초기화
42 | dist[start] = 0;
43 |
44 | // ❺ 우선순위 큐를 생성하고 시작 노드를 삽입
45 | PriorityQueue pq = new PriorityQueue<>((o1, o2) -> Integer.compare(o1.cost, o2.cost));
46 | pq.add(new Node(start, 0));
47 |
48 | while (!pq.isEmpty()) {
49 | // ❻ 현재 가장 거리가 짧은 노드를 가져옴
50 | Node now = pq.poll();
51 |
52 | // ❼ 만약 현재 노드의 거리 값이 큐에서 가져온 거리 값보다 크면, 해당 노드는 이미 방문한 것이므로 무시
53 | if (dist[now.dest] < now.cost)
54 | continue;
55 |
56 | // ❽ 현재 노드와 인접한 노드들의 거리 값을 계산하여 업데이트
57 | for (Node next : adjList[now.dest]) {
58 | // ❾ 기존에 발견했던 거리보다 더 짧은 거리를 발견하면 거리 값을 갱신하고 큐에 넣음
59 | if (dist[next.dest] > now.cost + next.cost) {
60 | dist[next.dest] = now.cost + next.cost;
61 | pq.add(new Node(next.dest, dist[next.dest]));
62 | }
63 | }
64 | }
65 |
66 | // ➓ 최단 거리를 담고 있는 배열을 반환
67 | return dist;
68 | }
69 |
70 | }
--------------------------------------------------------------------------------
/solution/37.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 |
3 | public class Solution {
4 |
5 | // ❶ 이동할 수 있는 방향을 나타내는 배열 rx, ry 선언
6 | private static final int[] rx = {0, 0, 1, -1};
7 | private static final int[] ry = {1, -1, 0, 0};
8 |
9 | private static class Node {
10 | int r, c;
11 |
12 | public Node(int r, int c) {
13 | this.r = r;
14 | this.c = c;
15 | }
16 | }
17 |
18 | public int solution(int[][] maps) {
19 | // ❷ 맵의 크기를 저장하는 변수 선언
20 | int N = maps.length;
21 | int M = maps[0].length;
22 |
23 | // ❸ 최단 거리를 저장할 배열 생성
24 | int[][] dist = new int[N][M];
25 |
26 | // ❹ bfs 탐색을 위한 큐 생성
27 | ArrayDeque queue = new ArrayDeque<>();
28 |
29 | // ❺ 시작 정점에 대해서 큐에 추가, 최단 거리 저장
30 | queue.addLast(new Node(0, 0));
31 | dist[0][0] = 1;
32 |
33 | // ❻ queue가 빌 때까지 반복
34 | while (!queue.isEmpty()) {
35 | Node now = queue.pollFirst();
36 |
37 | // ❼ 현재 위치에서 이동할 수 있는 모든 방향
38 | for (int i = 0; i < 4; i++) {
39 | int nr = now.r + rx[i];
40 | int nc = now.c + ry[i];
41 |
42 | // ❽ 맵 밖으로 나가는 경우 예외처리
43 | if (nr < 0 || nc < 0 || nr >= N || nc >= M)
44 | continue;
45 |
46 | // ❾ 벽으로 가는 경우 예외처리
47 | if (maps[nr][nc] == 0)
48 | continue;
49 |
50 | // ➓ 이동한 위치가 처음 방문하는 경우, queue에 추가하고 거리 갱신
51 | if (dist[nr][nc] == 0) {
52 | queue.addLast(new Node(nr, nc));
53 | dist[nr][nc] = dist[now.r][now.c] + 1;
54 | }
55 | }
56 | }
57 |
58 | // 목적지까지 최단 거리 반환, 목적지에 도달하지 못한 경우에는 -1 반환
59 | return dist[N - 1][M - 1] == 0 ? -1 : dist[N - 1][M - 1];
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/solution/38.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | private static boolean[] visit;
4 | private static int[][] computer;
5 |
6 | private static void dfs(int now) {
7 | visit[now] = true; // ❶ 현재 노드 방문 처리
8 | for (int i = 0; i < computer[now].length; i++) {
9 | // ❷ 연결되어 있으며 방문하지 않은 노드라면
10 | if (computer[now][i] == 1 && !visit[i]) {
11 | dfs(i); // ❸ 해당 노드를 방문하러 이동
12 | }
13 | }
14 | }
15 |
16 | public int solution(int n, int[][] computers) {
17 | int answer = 0;
18 | computer = computers;
19 | visit = new boolean[n]; // ❹ 방문 여부를 저장할 배열
20 |
21 | for (int i = 0; i < n; i++) {
22 | if (!visit[i]) { // ❺ 아직 방문하지 않은 노드라면 해당 노드를 시작으로 깊이 우선 탐색 진행
23 | dfs(i);
24 | answer++; // ❻ DFS로 연결된 노드들을 모두 방문하면서 네트워크 개수 증가
25 | }
26 | }
27 |
28 | return answer;
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/solution/39.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 |
3 | public class Solution {
4 |
5 | // ❶ 위, 아래, 왼쪽, 오른쪽 이동 방향
6 | private static final int[] dx = {0, 0, -1, 1};
7 | private static final int[] dy = {-1, 1, 0, 0};
8 |
9 | // ❷ 위치 정보(x, y)를 저장할 클래스 생성
10 | private static class Point {
11 | int nx, ny;
12 |
13 | public Point(int nx, int ny) {
14 | this.nx = nx;
15 | this.ny = ny;
16 | }
17 | }
18 |
19 | private static char[][] map;
20 | private static int N, M;
21 |
22 | public int solution(String[] maps) {
23 | N = maps.length;
24 | M = maps[0].length();
25 |
26 | // ❸ 미로에 대한 정보를 배열로 저장
27 | map = new char[N][M];
28 | for (int i = 0; i < N; i++) {
29 | map[i] = maps[i].toCharArray();
30 | }
31 |
32 | Point start = null, end = null, lever = null;
33 |
34 | // ❹ 시작 지점, 출구 그리고 레버의 위치를 찾음
35 | for (int i = 0; i < N; i++) {
36 | for (int j = 0; j < M; j++) {
37 | if (map[i][j] == 'S') start = new Point(j, i);
38 | else if (map[i][j] == 'E') end = new Point(j, i);
39 | else if (map[i][j] == 'L') lever = new Point(j, i);
40 | }
41 | }
42 |
43 | // ❺ 시작 자점 -> 레버, 레버 -> 출구까지의 최단 거리를 각각 구함
44 | int startLever = bfs(start, lever);
45 | int leverEnd = bfs(lever, end);
46 |
47 | // ❻ 도착 불가능한 경우는 -1, 도착 가능한 경우는 최단 거리를 반환
48 | if (startLever == -1 || leverEnd == -1)
49 | return -1;
50 | else
51 | return startLever + leverEnd;
52 | }
53 |
54 | // start -> end 로 너비 우선 탐색하여 최단거리 반환
55 | private static int bfs(Point start, Point end) {
56 | // ❼ 너비 우선 탐색 초기 과정
57 | int[][] dist = new int[N][M];
58 | ArrayDeque queue = new ArrayDeque<>();
59 |
60 | dist[start.ny][start.nx] = 1;
61 | queue.add(start);
62 |
63 | while (!queue.isEmpty()) {
64 | Point now = queue.poll();
65 |
66 | // ❽ 네 방향으로 이동
67 | for (int i = 0; i < 4; i++) {
68 | int nextX = now.nx + dx[i];
69 | int nextY = now.ny + dy[i];
70 |
71 | // ❾ 범위를 벗어나는 경우 예외 처리
72 | if (nextX < 0 || nextX >= M || nextY < 0 || nextY >= N)
73 | continue;
74 |
75 | // ➓ 이미 방문한 지점인 경우 탐색하지 않음
76 | if (dist[nextY][nextX] > 0)
77 | continue;
78 |
79 | // ⓫ X가 아닌 지점만 이동 가능
80 | if (map[nextY][nextX] == 'X')
81 | continue;
82 |
83 | // ⓬ 거리 1증가
84 | dist[nextY][nextX] = dist[now.ny][now.nx] + 1;
85 |
86 | // ⓭ 다음 정점을 큐에 넣음
87 | queue.add(new Point(nextX, nextY));
88 |
89 | // ⓮ 도착점에 도달하면 최단 거리를 반환
90 | if (nextX == end.nx && nextY == end.ny)
91 | return dist[end.ny][end.nx] - 1;
92 | }
93 | }
94 |
95 | // ⓯ 탐색을 종료할 때까지 도착 지점에 도달하지 못 했다면 -1 반환
96 | return -1;
97 | }
98 |
99 | }
--------------------------------------------------------------------------------
/solution/40.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 | import java.util.PriorityQueue;
4 |
5 | public class Solution {
6 |
7 | private static class Node {
8 | int dest, cost;
9 |
10 | public Node(int dest, int cost) {
11 | this.dest = dest;
12 | this.cost = cost;
13 | }
14 | }
15 |
16 | public int solution(int N, int[][] road, int K) {
17 | // ❶ 인접 리스트를 저장할 ArrayList 배열 초기화
18 | ArrayList[] adjList = new ArrayList[N + 1];
19 | for (int i = 1; i <= N; i++) {
20 | adjList[i] = new ArrayList<>();
21 | }
22 |
23 | // ❷ road 정보를 인접 리스트로 저장
24 | for (int[] edge : road) {
25 | adjList[edge[0]].add(new Node(edge[1], edge[2]));
26 | adjList[edge[1]].add(new Node(edge[0], edge[2]));
27 | }
28 |
29 | int[] dist = new int[N + 1];
30 | // ❸ 모든 노드의 거리 값을 무한대로 초기화
31 | Arrays.fill(dist, Integer.MAX_VALUE);
32 |
33 | // ❹ 우선순위 큐를 생성하고 시작 노드를 삽입
34 | PriorityQueue pq = new PriorityQueue<>((o1, o2) -> Integer.compare(o1.cost, o2.cost));
35 | pq.add(new Node(1, 0));
36 | dist[1] = 0;
37 |
38 | while (!pq.isEmpty()) {
39 | Node now = pq.poll();
40 |
41 | if (dist[now.dest] < now.cost)
42 | continue;
43 |
44 | // ❺ 인접한 노드들의 최단 거리를 갱신하고 우선순위 큐에 추가
45 | for (Node next : adjList[now.dest]) {
46 | if (dist[next.dest] > now.cost + next.cost) {
47 | dist[next.dest] = now.cost + next.cost;
48 | pq.add(new Node(next.dest, dist[next.dest]));
49 | }
50 | }
51 | }
52 |
53 | int answer = 0;
54 |
55 | // ❻ dist 배열에서 K 이하인 값의 개수를 구하여 반환
56 | for (int i = 1; i <= N; i++) {
57 | if (dist[i] <= K) answer++;
58 | }
59 |
60 | return answer;
61 | }
62 |
63 | }
--------------------------------------------------------------------------------
/solution/41.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 |
3 | public class Solution {
4 |
5 | private static class Node {
6 | int x, y, direction, cost;
7 |
8 | public Node(int x, int y, int direction, int cost) {
9 | this.x = x;
10 | this.y = y;
11 | this.direction = direction;
12 | this.cost = cost;
13 | }
14 | }
15 |
16 | // 순서가 반드시 (0, -1), (-1, 0), (0, 1), (1, 0) 순서로 되어야합니다. 코너 계산에 필요함
17 | private static final int[] rx = {0, -1, 0, 1};
18 | private static final int[] ry = {-1, 0, 1, 0};
19 |
20 | private static int N;
21 | private static int[][][] visited;
22 |
23 | // ❶ 주어진 좌표가 보드의 범위 내에 있는지 확인
24 | private static boolean isValid(int x, int y) {
25 | return 0 <= x && x < N && 0 <= y && y < N;
26 | }
27 |
28 | // ❷ 주어진 좌표가 차단되었거나 이동할 수 없는지 확인
29 | private static boolean isBlocked(int[][] board, int x, int y) {
30 | return (x == 0 && y == 0) || !isValid(x, y) || board[x][y] == 1;
31 | }
32 |
33 | // ❸ 이전 방향과 현재 방향에 따라 비용 계산
34 | private static int calculateCost(int direction, int prevDirection, int cost) {
35 | if (prevDirection == -1 || (prevDirection - direction) % 2 == 0)
36 | return cost + 100;
37 | return cost + 600;
38 | }
39 |
40 | // ❹ 주어진 좌표와 방향이 아직 방문하지 않았거나 새 비용이 더 작은 경우
41 | private static boolean isShouldUpdate(int x, int y, int direction, int newCost) {
42 | return visited[x][y][direction] == 0 || visited[x][y][direction] > newCost;
43 | }
44 |
45 | public int solution(int[][] board) {
46 | ArrayDeque queue = new ArrayDeque<>();
47 | queue.add(new Node(0, 0, -1, 0));
48 | N = board.length;
49 | visited = new int[N][N][4];
50 |
51 | int answer = Integer.MAX_VALUE;
52 |
53 | // ❺ 큐가 빌 때까지 반복
54 | while (!queue.isEmpty()) {
55 | Node now = queue.poll();
56 |
57 | // ❻ 가능한 모든 방향에 대해 반복
58 | for (int i = 0; i < 4; i++) {
59 | int new_x = now.x + rx[i];
60 | int new_y = now.y + ry[i];
61 |
62 | // ❼ 이동할 수 없는 좌표는 건너뛰기
63 | if (isBlocked(board, new_x, new_y)) {
64 | continue;
65 | }
66 |
67 | int new_cost = calculateCost(i, now.direction, now.cost);
68 |
69 | // ❽ 도착지에 도달한 경우 최소 비용 업데이트
70 | if (new_x == N - 1 && new_y == N - 1) {
71 | answer = Math.min(answer, new_cost);
72 | }
73 | // ❾ 좌표와 방향이 아직 방문하지 않았거나 새 비용이 더 작은 경우 큐에 추가
74 | else if(isShouldUpdate(new_x, new_y, i, new_cost)) {
75 | queue.add(new Node(new_x, new_y, i, new_cost));
76 | visited[new_x][new_y][i] = new_cost;
77 | }
78 | }
79 | }
80 |
81 | return answer;
82 | }
83 |
84 | }
--------------------------------------------------------------------------------
/solution/42.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 |
3 | public class Solution {
4 |
5 | private static boolean[] visited;
6 | private static ArrayList[] adjList;
7 | private static int N, answer;
8 |
9 | public static int solution(int n, int[][] wires) {
10 | N = n;
11 | answer = n - 1;
12 |
13 | // ❶ 전선의 연결 정보를 저장할 인접 리스트 초기화
14 | adjList = new ArrayList[n + 1];
15 | for (int i = 1; i <= n; i++) {
16 | adjList[i] = new ArrayList<>();
17 | }
18 |
19 | // ❷ 전선의 연결 정보를 인접 리스트에 저장
20 | for (int[] wire : wires) {
21 | adjList[wire[0]].add(wire[1]);
22 | adjList[wire[1]].add(wire[0]);
23 | }
24 |
25 | visited = new boolean[n + 1];
26 |
27 | // ❸ 깊이 우선 탐색 시작
28 | dfs(1);
29 |
30 | return answer;
31 | }
32 |
33 | private static int dfs(int now) {
34 | visited[now] = true;
35 |
36 | // ❹ 자식 노드의 수를 저장하고 반환할 변수 선언
37 | int sum = 0;
38 | // ❺ 연결된 모든 전선을 확인
39 | for (int next : adjList[now]) {
40 | if (!visited[next]) {
41 | // ❻ (전체 노드 - 자식 트리의 노드 수) - (자식 트리의 노드 수) 의 절대값이 가장 작은 값을 구함
42 | int cnt = dfs(next); // 자식 트리가 가진 노드의 수
43 | answer = Math.min(answer, Math.abs(N - cnt * 2));
44 | // ❼ 자식 노드의 수를 더함
45 | sum += cnt;
46 | }
47 | }
48 |
49 | // ❽ 전체 자식 노드의 수에 1(현재 now 노드)을 더해서 반환
50 | return sum + 1;
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/solution/43.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(solution(5));
7 | System.out.println(solution(2));
8 | System.out.println(solution(7));
9 | }
10 |
11 | // ❶ 조합 결과를 담을 리스트
12 | private static ArrayList> result;
13 | private static int n;
14 | private static void backtrack(int sum, ArrayList selectedNums, int start) {
15 | // ❷ 합이 10이 되면 결과 리스트에 추가
16 | if (sum == 10) {
17 | result.add(selectedNums);
18 | return;
19 | }
20 |
21 | // ❸ 다음에 선택할 수 있는 숫자들을 하나씩 선택하면서
22 | for (int i = start; i <= n; i++) {
23 | // ❹ 선택한 숫자의 합이 10보다 작거나 같으면
24 | if (sum + i <= 10) {
25 | ArrayList list = new ArrayList<>(selectedNums);
26 | list.add(i);
27 | // ❺ 백트래킹 메소드를 재귀적으로 호출합니다.
28 | backtrack(sum + i, list, i + 1);
29 | }
30 | }
31 | }
32 |
33 | // 이 부분을 변경해서 실행해보세요.
34 | private static ArrayList> solution(int N) {
35 | result = new ArrayList<>();
36 | n = N;
37 |
38 | // ❻ 백트래킹 메소드 호출
39 | backtrack(0, new ArrayList<>(), 1);
40 |
41 | return result;
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/solution/44.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | int[][] board1 = {
7 | {5, 3, 0, 0, 7, 0, 0, 0, 0},
8 | {6, 0, 0, 1, 9, 5, 0, 0, 0},
9 | {0, 9, 8, 0, 0, 0, 0, 6, 0},
10 | {8, 0, 0, 0, 6, 0, 0, 0, 3},
11 | {4, 0, 0, 8, 0, 3, 0, 0, 1},
12 | {7, 0, 0, 0, 2, 0, 0, 0, 6},
13 | {0, 6, 0, 0, 0, 0, 2, 8, 0},
14 | {0, 0, 0, 4, 1, 9, 0, 0, 5},
15 | {0, 0, 0, 0, 8, 0, 0, 7, 9}
16 | };
17 | System.out.println(Arrays.deepToString(solution(board1)));
18 |
19 | int[][] board2 = {
20 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
21 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
22 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
23 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
24 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
25 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
26 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
27 | {0, 0, 0, 0, 0, 0, 0, 0, 0},
28 | {0, 0, 0, 0, 0, 0, 0, 0, 0}
29 | };
30 | System.out.println(Arrays.deepToString(solution(board2)));
31 | }
32 |
33 | private static class Block {
34 | int i, j;
35 |
36 | public Block(int i, int j) {
37 | this.i = i;
38 | this.j = j;
39 | }
40 | }
41 |
42 | private static int[][] Board;
43 |
44 | private static boolean isValid(int num, int row, int col) {
45 | // ❶ 현재 위치에 num이 들어갈 수 있는지 검사
46 | return !(inRow(num, row) || inCol(num, col) || inBox(num, row, col));
47 | }
48 |
49 | private static boolean inRow(int num, int row) {
50 | // ❷ 해당 행에 num이 있는지 확인
51 | return Arrays.stream(Board[row]).anyMatch(n -> n == num);
52 | }
53 |
54 | private static boolean inCol(int num, int col) {
55 | // ❸ 해당 열에 num이 있는지 확인
56 | for (int i = 0; i < 9; i++) {
57 | if (Board[i][col] == num) return true;
58 | }
59 | return false;
60 | }
61 |
62 | private static boolean inBox(int num, int row, int col) {
63 | // ❹ 현재 위치의 3 x 3 박스에 num이 있는지 확인
64 | int boxRow = (row / 3) * 3;
65 | int boxCol = (col / 3) * 3;
66 |
67 | for (int i = boxRow; i < boxRow + 3; i++) {
68 | for (int j = boxCol; j < boxCol + 3; j++) {
69 | if (Board[i][j] == num) {
70 | return true;
71 | }
72 | }
73 | }
74 |
75 | return false;
76 | }
77 |
78 | private static Block findEmptyPosition() {
79 | // ❺ 스도쿠 보드에서 비어 있는 위치 반환
80 | for (int i = 0; i < 9; i++) {
81 | for (int j = 0; j < 9; j++) {
82 | if (Board[i][j] == 0)
83 | return new Block(i, j);
84 | }
85 | }
86 | return null;
87 | }
88 |
89 | private static boolean findSolution() {
90 | // ❻ 비어 있는 위치에 가능한 숫자를 넣어가며 스도쿠 해결
91 | Block emptyPos = findEmptyPosition();
92 | // ❼ 빈칸이 없으면 스도쿠가 해결된 것으로 간주
93 | if (emptyPos == null)
94 | return true;
95 |
96 | int row = emptyPos.i;
97 | int col = emptyPos.j;
98 |
99 | for (int num = 1; num <= 9; num++) {
100 | if (isValid(num, row, col)) {
101 | Board[row][col] = num;
102 | // ❽ 다음 빈칸을 재귀 탐색
103 | if (findSolution()) {
104 | return true;
105 | }
106 | // ❾ 가능한 숫자가 없으면 원래의 0으로 되돌림
107 | Board[row][col] = 0;
108 | }
109 | }
110 |
111 | return false;
112 | }
113 |
114 | // 이 부분을 변경해서 실행해보세요.
115 | private static int[][] solution(int[][] board) {
116 | Board = board;
117 | findSolution();
118 | return board;
119 | }
120 |
121 | }
--------------------------------------------------------------------------------
/solution/45.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | private static int answer;
4 | private static int[][] Dungeons;
5 | private static boolean[] visited;
6 |
7 | // 백트래킹을 위한 DFS
8 | private static void backtrack(int k, int cnt) {
9 | for (int i = 0; i < Dungeons.length; i++) {
10 | // ❶ 현재 피로도(k)가 i번째 던전의 최소 필요 피로도보다 크거나 같고,
11 | // i번째 던전을 방문한 적이 없다면
12 | if (!visited[i] && k >= Dungeons[i][0]) {
13 | visited[i] = true; // i번째 던전을 방문 처리
14 | // ❷ 현재까지의 최대 탐험 가능 던전 수와
15 | // i번째 던전에서 이동할 수 있는 최대 탐험 가능 던전 수 중 큰 값을 선택하여 업데이트
16 | backtrack(k - Dungeons[i][1], cnt + 1);
17 | answer = Math.max(answer, cnt + 1);
18 | visited[i] = false; // i번째 던전을 다시 방문 취소
19 | }
20 | }
21 | }
22 |
23 | public int solution(int k, int[][] dungeons) {
24 | answer = 0;
25 | Dungeons = dungeons;
26 | // ❸ 던전 방문 여부를 저장할 배열
27 | visited = new boolean[dungeons.length];
28 |
29 | backtrack(k, 0); // ❹ DFS 메소드 수행
30 |
31 | return answer;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/solution/46.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | private static int N;
4 | private static boolean[] width;
5 | private static boolean[] diagonal1;
6 | private static boolean[] diagonal2;
7 |
8 | // ❶ 퀸이 서로 공격할 수 없는 위치에 놓이는 경우의 수를 구하는 함수
9 | private static int getAns(int y) {
10 | int ans = 0;
11 | // ❷ 모든 행에 대해서 퀸의 위치가 결장되었을 경우
12 | if (y == N) {
13 | // ❸ 해결 가능한 경우의 수를 1 증가시킴
14 | ans++;
15 | }
16 | else {
17 | // ❹ 현재 행에서 퀸이 놓일 수 있는 모든 위치를 시도
18 | for (int i = 0; i < N; i++) {
19 | // ❺ 해당 위치에 이미 퀸이 있는 경우, 대각선상에 퀸이 있는 경우 스킵
20 | if (width[i] || diagonal1[i + y] || diagonal2[i - y + N])
21 | continue;
22 |
23 | // ❻ 해당 위치에 퀸을 놓음
24 | width[i] = diagonal1[i + y] = diagonal2[i - y + N] = true;
25 | // ❼ 다음 행으로 이동하여 재귀적으로 해결 가능한 경우의 수 찾기
26 | ans += getAns(y + 1);
27 | // ❽ 해당 위치에 놓인 퀸을 제거함
28 | width[i] = diagonal1[i + y] = diagonal2[i - y + N] = false;
29 | }
30 | }
31 |
32 | return ans;
33 | }
34 |
35 | public int solution(int n) {
36 | N = n;
37 | width = new boolean[n];
38 | diagonal1 = new boolean[n * 2];
39 | diagonal2 = new boolean[n * 2];
40 |
41 | int answer = getAns(0);
42 | return answer;
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/solution/47.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | private static int max;
6 | private static int[] answer;
7 | private static int[] apeach;
8 |
9 | // ❶ 주어진 조합에서 각각의 점수 계산
10 | private static int getScore(int[] ryan) {
11 | int score = 0;
12 | for (int i = 0; i <= 10; i++) {
13 | if (ryan[i] + apeach[i] > 0) {
14 | score += ryan[i] > apeach[i] ? (10 - i) : -(10 - i);
15 | }
16 | }
17 | return score;
18 | }
19 |
20 | // ❷ 최대 차이와 라이언의 과녁 저장
21 | private static void calculateDiff(int[] ryan) {
22 | int score = getScore(ryan);
23 | if (max < score) {
24 | max = score;
25 | answer = ryan.clone();
26 | }
27 | // 점수가 같으면 가장 낮은 점수를 더 많이 맞힌 경우를 찾음
28 | else if (max > 0 && max == score) {
29 | for (int i = 10; i >= 0; i--) {
30 | if(answer[i] != ryan[i]) {
31 | if (answer[i] < ryan[i]) {
32 | answer = ryan.clone();
33 | }
34 | break;
35 | }
36 | }
37 | }
38 | }
39 |
40 | // ❸ 가능한 라이언의 과녁 점수 조합의 모든 경우를 구함
41 | private static void backtrack(int n, int idx, int[] ryan) {
42 | if (n == 0) {
43 | calculateDiff(ryan);
44 | return;
45 | }
46 |
47 | for (int i = idx; i <= 10; i++) {
48 | int cnt = i == 10 ? n : apeach[i] + 1;
49 | if (cnt > n) {
50 | continue;
51 | }
52 | ryan[i] = cnt;
53 | backtrack(n - cnt, i + 1, ryan);
54 | ryan[i] = 0;
55 | }
56 | }
57 |
58 | public static int[] solution(int n, int[] info) {
59 | apeach = info;
60 | max = 0;
61 | backtrack(n, 0, new int[11]);
62 | // ❹ 최대 차이가 0인 경우 -1 반환, 아니면 answer 반환
63 | return max == 0 ? new int[]{-1} : answer;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/solution/48.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | private static int length, answer;
6 | private static int[] Weak;
7 | private static boolean[] used;
8 |
9 | // ❶ dist 배열의 친구들로 모든 외벽이 점검 가능한지 확인
10 | private static boolean check(int[] dist) {
11 | // ❷ 점검을 시작하는 외벽을 0 부터 length 까지 전부 확인함
12 | for (int i = 0; i < length; i++) {
13 | int idx = i;
14 | // ❸ 각 친구가 점검 가능한 외벽을 모두 점검하며 진행
15 | for (int distance : dist) {
16 | int position = Weak[idx++] + distance;
17 | while (idx < Weak.length && Weak[idx] <= position) {
18 | idx++;
19 | }
20 | }
21 | // ❹ 모든 외벽을 점검 가능하면 true 반환
22 | if (idx - i >= length)
23 | return true;
24 | }
25 | // ❺ 모든 외벽을 점검할 수 없으면 false 반환
26 | return false;
27 | }
28 |
29 | // ❻ n개의 숫자를 나열하는 모든 경우의 수를 구함
30 | private static void backtrack(int n, int[] dist, int[] org) {
31 | if (n == org.length) {
32 | // ❼ 모든 외벽이 점검 가능하면 답 저장
33 | if (check(dist))
34 | answer = n;
35 | return;
36 | }
37 |
38 | // ❽ 한 번 사용한 친구는 다시 사용하지 않도록 used 배열을 활용하여 백트래킹
39 | for (int i = 0; i < org.length; i++) {
40 | if (!used[i]) {
41 | used[i] = true;
42 | dist[n] = org[i];
43 | backtrack(n + 1, dist, org);
44 | used[i] = false;
45 | }
46 | }
47 | }
48 |
49 | public static int solution(int n, int[] weak, int[] dist) {
50 | // ❾ 주어진 weak 지점들을 선형으로 만들어 줌
51 | length = weak.length;
52 | Weak = new int[length * 2];
53 | for (int i = 0; i < 2; i++) {
54 | for (int j = 0; j < length; j++) {
55 | Weak[j + (i * length)] = weak[j] + (i * n);
56 | }
57 | }
58 |
59 | // ➓ 오름차순으로 정렬
60 | Arrays.sort(dist);
61 | answer = -1; // 답을 -1 로 초기화
62 | used = new boolean[dist.length]; // used 배열 생성
63 |
64 | // ⓫ 가장 점검 범위가 큰 친구부터 1명 씩 늘려가며 답을 탐색
65 | for (int i = 1; i <= dist.length; i++) {
66 | int[] org = new int[i];
67 | System.arraycopy(dist, dist.length - i, org, 0, i);
68 | backtrack(0, new int[i], org);
69 | if (answer > 0) // 답을 찾았으면 종료해야 함
70 | break;
71 | }
72 |
73 | return answer;
74 | }
75 |
76 | }
--------------------------------------------------------------------------------
/solution/49.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Comparator;
3 |
4 | public class Solution {
5 |
6 | // 백트래킹을 위한 재귀 메소드의 반환값을 저장함
7 | private static class Result {
8 | boolean win;
9 | int step;
10 |
11 | public Result(boolean win, int step) {
12 | this.win = win;
13 | this.step = step;
14 | }
15 | }
16 |
17 | // ❶ 게임판의 행과 열의 개수를 저장합니다.
18 | private static int ROW, COL;
19 |
20 | // ❷ 이동할 수 있는 방향을 저장합니다. 상, 우, 하, 좌 순서로 저장되어 있습니다.
21 | private static final int[] DR = {0, 1, 0, -1};
22 | private static final int[] DC = {-1, 0, 1, 0};
23 |
24 | private static boolean[][] visited;
25 |
26 | private static int[][] Board;
27 |
28 | // ❸ 주어진 위치가 유효한 위치인지 확인하는 메소드입니다.
29 | private static boolean isVaildPos(int r, int c) {
30 | return 0 <= r && r < ROW && 0 <= c && c < COL;
31 | }
32 |
33 | // ❹ 재귀적으로 호출되는 메소드입니다.
34 | private static Result recursive(int[] alpha, int[] beta, int step) {
35 | // ❺ 현재 플레이어의 위치와 이동 가능한지 여부,
36 | // 상대 플레이어가 이긴 경우를 저장하는 변수들입니다.
37 | int[] now = step % 2 == 0 ? alpha : beta;
38 | boolean canMove = false;
39 | boolean isOpponentWinner = true;
40 |
41 | // ❻ 이긴 경우와 지는 경우를 저장하는 리스트입니다.
42 | ArrayList winSteps = new ArrayList<>();
43 | ArrayList loseSteps = new ArrayList<>();
44 |
45 | // ❼ 현재 위치에서 이동할 수 있는 모든 방향으로 이동해봅니다.
46 | for (int i = 0; i < 4; i++) {
47 | int nr = now[0] + DR[i];
48 | int nc = now[1] + DC[i];
49 | // ❽ 이동할 수 있는 위치인 경우
50 | if (isVaildPos(nr, nc) && !visited[nr][nc] && Board[nr][nc] == 1) {
51 | canMove = true;
52 | // ❾ 두 플레이어의 위치가 같으면 A 플레이어가 이긴 것이므로 true와 step + 1을 반환합니다.
53 | if (alpha[0] == beta[0] && alpha[1] == beta[1])
54 | return new Result(true, step + 1);
55 |
56 | // ➓ 재귀적으로 호출하여 이긴 여부와 남은 턴 수를 가져옵니다.
57 | visited[now[0]][now[1]] = true;
58 | Result result = step % 2 == 0 ? recursive(new int[]{nr, nc}, beta, step + 1)
59 | : recursive(alpha, new int[]{nr, nc}, step + 1);
60 | visited[now[0]][now[1]] = false;
61 |
62 | // ⓫ 상대 플레이어가 이긴 경우만 true로 유지합니다.
63 | isOpponentWinner &= result.win;
64 | // ⓬ 이긴 경우와 지는 경우를 저장합니다.
65 | if (result.win)
66 | winSteps.add(result.step);
67 | else
68 | loseSteps.add(result.step);
69 | }
70 | }
71 |
72 | // ⓭ 이동할 수 있는 위치가 없는 경우
73 | if (!canMove)
74 | return new Result(false, step);
75 | // ⓮ 상대 플레이어가 이긴 경우
76 | if (isOpponentWinner)
77 | return new Result(false, winSteps.stream().max(Comparator.comparingInt(o -> o)).get());
78 | // ⓯ 현재 플레이어가 이긴 경우
79 | return new Result(true, loseSteps.stream().min(Comparator.comparingInt(o -> o)).get());
80 | }
81 |
82 | public static int solution(int[][] board, int[] aloc, int[] bloc) {
83 | Board = board;
84 | ROW = board.length;
85 | COL = board[0].length;
86 | visited = new boolean[ROW][COL];
87 | // 16 A 플레이어가 이길 때까지 걸리는 최소 턴 수를 반환합니다.
88 | return recursive(aloc, bloc, 0).step;
89 | }
90 |
91 | }
--------------------------------------------------------------------------------
/solution/50.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public static void main(String[] args) {
4 | System.out.println(solution("hello"));
5 | System.out.println(solution("algorithm"));
6 | }
7 |
8 | // 이 부분을 변경해서 실행해보세요.
9 | private static String solution(String s) {
10 | int[] counts = new int[26]; // ❶ 알파벳 개수(26개)만큼 빈도수 배열 생성
11 |
12 | // ❷ 문자열의 각 문제에 대한 빈도수를 count배열에 저장
13 | for (char c : s.toCharArray()) {
14 | counts[c - 'a']++;
15 | }
16 |
17 | // ❸ 빈도수 배열을 순회화면서 정렬된 문자열을 생성
18 | StringBuilder sortedStr = new StringBuilder();
19 | for (int i = 0; i < 26; i++) {
20 | for (int j = 0; j < counts[i]; j++) {
21 | sortedStr.append((char)(i + 'a'));
22 | }
23 | }
24 |
25 | return sortedStr.toString();
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/solution/51.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(Arrays.toString(solution(new int[]{1, 3, 5}, new int[]{2, 4, 6})));
7 | System.out.println(Arrays.toString(solution(new int[]{1, 2, 3}, new int[]{4, 5, 6})));
8 | }
9 |
10 | // 이 부분을 변경해서 실행해보세요.
11 | private static int[] solution(int[] arr1, int[] arr2) {
12 | // 정렬된 배열을 저장할 배열 생성
13 | int[] merged = new int[arr1.length + arr2.length];
14 | int k = 0, i = 0, j = 0; // 3개 배열의 인덱스 초기화
15 |
16 | // 두 배열을 순회하면서 정렬된 배열을 생성
17 | while (i < arr1.length && j < arr2.length) {
18 | merged[k++] = arr1[i] <= arr2[j] ? arr1[i++] : arr2[j++];
19 | }
20 |
21 | // arr1 이나 arr2 중 남아 있는 원소들을 정렬된 배열 뒤에 추가
22 | while (i < arr1.length) {
23 | merged[k++] = arr1[i++];
24 | }
25 | while (j < arr2.length) {
26 | merged[k++] = arr2[j++];
27 | }
28 |
29 | return merged;
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/solution/52.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public String[] solution(String[] strings, int n) {
6 | Arrays.sort(strings, (o1, o2) -> o1.charAt(n) == o2.charAt(n) ? o1.compareTo(o2) : Character.compare(o1.charAt(n), o2.charAt(n)));
7 | return strings;
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/solution/53.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 | import java.util.Collections;
3 |
4 | public class Solution {
5 |
6 | public long solution(long n) {
7 | // ❶ 정수 n을 문자열로 변환하고 각 자릿수를 배열로 저장합니다.
8 | String[] digits = String.valueOf(n).split("");
9 |
10 | // ❷ 내림차순으로 정렬합니다.
11 | Arrays.sort(digits, Collections.reverseOrder());
12 |
13 | // ❸ 정렬된 숫자를 다시 하나의 문자열로 합칩니다.
14 | StringBuilder sb = new StringBuilder();
15 | for (String digit : digits)
16 | sb.append(digit);
17 |
18 | // ❹ 문자열을 long형으로 변환하여 반환합니다.
19 | return Long.parseLong(sb.toString());
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/solution/54.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public int[] solution(int[] array, int[][] commands) {
6 | int[] answer = new int[commands.length];
7 |
8 | for (int c = 0; c < commands.length; c++) {
9 | int i = commands[c][0];
10 | int j = commands[c][1];
11 | int k = commands[c][2];
12 |
13 | // ❶ i번째 부터 j번째 까지 자르기
14 | int[] slicedArr = Arrays.copyOfRange(array, i - 1, j);
15 | // ❷ 자른 배열을 정렬하기
16 | Arrays.sort(slicedArr);
17 | // ❸ k번째 원소 구하기
18 | answer[c] = slicedArr[k - 1];
19 | }
20 |
21 | return answer;
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/solution/55.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 |
3 | public class Solution {
4 |
5 | public String solution(int[] numbers) {
6 | // ❶ int형 정수 배열을 문자열로 바꾸어 list에 저장합니다.
7 | ArrayList list = new ArrayList<>();
8 | for (int number : numbers) {
9 | list.add(String.valueOf(number));
10 | }
11 |
12 | // ❷ 조합하여 비교하여 더 큰 수를 기준으로 내림차순 정렬합니다.
13 | list.sort((o1, o2) -> {
14 | int a = Integer.parseInt(o1 + o2);
15 | int b = Integer.parseInt(o2 + o1);
16 | return Integer.compare(b, a);
17 | });
18 |
19 | // ❸ 정렬된 수를 나열하여 문자열로 만듭니다.
20 | StringBuilder sb = new StringBuilder();
21 | for (String s : list) {
22 | sb.append(s);
23 | }
24 |
25 | // ❹ 문자열을 반환합니다. 맨앞에 "0" 이 있는 경우는 "0"만 반환합니다.
26 | return sb.charAt(0) == '0' ? "0" : sb.toString();
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/solution/56.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 | import java.util.HashSet;
3 |
4 | public class Solution {
5 |
6 | public int[] solution(String s) {
7 | // ❶ 문자열 s에서 대괄호를 제거하고 ","을 기준으로 나누어 배열에 저장한 후 길이 기준으로 오름차순 정렬합니다.
8 | s = s.substring(0, s.length() - 2).replace("{", "");
9 | String[] arr = s.split("},");
10 | Arrays.sort(arr, (o1, o2) -> Integer.compare(o1.length(), o2.length()));
11 |
12 | HashSet set = new HashSet<>();
13 | int[] answer = new int[arr.length];
14 |
15 | // ❷ 각 원소를 순회하면서 이전 원소와 차이 나는 부분을 구합니다.
16 | for (int i = 0; i < arr.length; i++) {
17 | String[] numbers = arr[i].split(",");
18 | for (String number : numbers) {
19 | if (!set.contains(number)) {
20 | answer[i] = Integer.parseInt(number);
21 | set.add(number);
22 | }
23 | }
24 | }
25 |
26 | return answer;
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/solution/57.java:
--------------------------------------------------------------------------------
1 | import java.util.PriorityQueue;
2 |
3 | public class Solution {
4 |
5 | private static class Node {
6 | int i, j, cost;
7 |
8 | public Node(int i, int j, int cost) {
9 | this.i = i;
10 | this.j = j;
11 | this.cost = cost;
12 | }
13 | }
14 |
15 | public int solution(int[][] land, int height) {
16 | int answer = 0;
17 | int n = land.length;
18 |
19 | // ❶ 주변 노드 탐색을 위한 di, dj
20 | int[] di = {-1, 0, 1, 0};
21 | int[] dj = {0, 1, 0, -1};
22 |
23 | boolean[][] visited = new boolean[n][n];
24 |
25 | // ❷ 시작 노드 추가
26 | PriorityQueue pq = new PriorityQueue<>((o1, o2) -> Integer.compare(o1.cost, o2.cost));
27 | pq.add(new Node(0, 0, 0));
28 |
29 | // ❸ BFS + 우선순위 큐로 다음 노드 관리
30 | while (!pq.isEmpty()) {
31 | Node now = pq.poll();
32 | // ❹ 아직 방문하지 않은 경로만 탐색
33 | if (visited[now.i][now.j])
34 | continue;
35 |
36 | visited[now.i][now.j] = true;
37 | // ❺ 현재까지 비용을 합산
38 | answer += now.cost;
39 |
40 | for (int i = 0; i < 4; i++) {
41 | int ni = now.i + di[i];
42 | int nj = now.j + dj[i];
43 |
44 | // ❻ 유효한 인덱스가 아닐 경우
45 | if (!(0 <= ni && ni < n && 0 <= nj && nj < n))
46 | continue;
47 |
48 | int tempCost = Math.abs(land[now.i][now.j] - land[ni][nj]);
49 | // ❼ 입력으로 주어진 height 보다 높이차가 큰 경우
50 | int newCost = tempCost > height ? tempCost : 0;
51 | // ❽ 다음 경로를 add
52 | pq.add(new Node(ni, nj, newCost));
53 | }
54 | }
55 |
56 | return answer;
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/solution/58.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public boolean solution(String[] phone_book) {
6 | // ❶ 전화번호부 정렬
7 | Arrays.sort(phone_book);
8 |
9 | // ❷ 전화번호부에서 연속된 두 개의 전화번호 비교
10 | for (int i = 0; i < phone_book.length - 1; i++) {
11 | if (phone_book[i + 1].startsWith(phone_book[i]))
12 | return false;
13 | }
14 |
15 | // ❸ 모든 전화번호를 비교한 후에도 반환되지 않았다면, 접두어가 없는 경우이므로 true 반환
16 | return true;
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/solution/59.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | int[][] arr1 = {
7 | {1, 2, 3, 4},
8 | {5, 6, 7, 8},
9 | {9, 10, 11, 12},
10 | {13, 14, 15, 16}
11 | };
12 | int n1 = 1;
13 | System.out.println(Arrays.deepToString(solution(arr1, n1)));
14 | int[][] arr2 = {
15 | {1, 2, 3, 4},
16 | {5, 6, 7, 8},
17 | {9, 10, 11, 12},
18 | {13, 14, 15, 16}
19 | };
20 | int n2 = 2;
21 | System.out.println(Arrays.deepToString(solution(arr2, n2)));
22 | }
23 |
24 | // ❶ 2차원 배열을 인자로 받고, 90도 회전시키는 메소드
25 | private static int[][] rotate90(int[][] arr) {
26 | // ❷ 배열의 크기 저장
27 | int n = arr.length;
28 |
29 | // ❸ 배열의 크기와 동일한 2차원 배열 생성(초기값은 0)
30 | int[][] rotatedArr = new int[n][n];
31 |
32 | // ❹ 배열을 90도 회전
33 | for (int i = 0; i < n; i++) {
34 | for (int j = 0; j < n; j++) {
35 | rotatedArr[j][n - i - 1] = arr[i][j];
36 | }
37 | }
38 |
39 | // ❺ 90도로 회전한 배열 반환
40 | return rotatedArr;
41 | }
42 |
43 | // 이 부분을 변경해서 실행해보세요.
44 | private static int[][] solution(int[][] arr, int n) {
45 | // ❻ 90도 회전 메소드 호출
46 | for (int i = 0; i < n; i++) {
47 | arr = rotate90(arr);
48 | }
49 | return arr;
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/solution/60.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | int[][] matrix1_1 = {
7 | {1, 2, 3},
8 | {4, 5, 6},
9 | {7, 8, 9}
10 | };
11 | int[][] matrix2_1 = {
12 | {9, 8, 7},
13 | {6, 5, 4},
14 | {3, 2, 1}
15 | };
16 | System.out.println(Arrays.deepToString(solution(matrix1_1, matrix2_1)));
17 |
18 | int[][] matrix1_2 = {
19 | {2, 4, 6},
20 | {1, 3, 5},
21 | {7, 8, 9}
22 | };
23 | int[][] matrix2_2 = {
24 | {9, 1, 2},
25 | {4, 5, 6},
26 | {7, 3, 8}
27 | };
28 | System.out.println(Arrays.deepToString(solution(matrix1_2, matrix2_2)));
29 | }
30 |
31 | private static int[][] multiplyMatrices(int[][] matrix1, int[][] matrix2) {
32 | // ❶ 결과 행렬을 0으로 초기화합니다.
33 | int[][] result = new int[3][3];
34 |
35 | // ❷ 행렬 곱셈을 수행합니다.
36 | for (int i = 0; i < 3; i++) {
37 | for (int j = 0; j < 3; j++) {
38 | for (int k = 0; k < 3; k++) {
39 | result[i][j] += matrix1[i][k] * matrix2[k][j];
40 | }
41 | }
42 | }
43 |
44 | return result;
45 | }
46 |
47 | private static int[][] transposeMatrix(int[][] matrix) {
48 | // ❸ 결과 행렬을 0으로 초기화합니다.
49 | int[][] result = new int[3][3];
50 |
51 | // 전치 행렬을 계산합니다.
52 | for (int i = 0; i < 3; i++) {
53 | for (int j = 0; j < 3; j++) {
54 | result[j][i] = matrix[i][j];
55 | }
56 | }
57 |
58 | return result;
59 | }
60 |
61 | // 이 부분을 변경해서 실행해보세요.
62 | private static int[][] solution(int[][] matrix1, int[][] matrix2) {
63 | // 주어진 두 행렬을 곱합니다.
64 | int[][] multiplied = multiplyMatrices(matrix1, matrix2);
65 |
66 | // 곱셈 결과의 전치 행렬을 계산합니다.
67 | int[][] transposed = transposeMatrix(multiplied);
68 |
69 | return transposed;
70 | }
71 |
72 | }
--------------------------------------------------------------------------------
/solution/61.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(Arrays.deepToString(solution(3)));
7 | System.out.println(Arrays.deepToString(solution(4)));
8 | }
9 |
10 | // 이 부분을 변경해서 실행해보세요.
11 | private static int[][] solution(int n) {
12 | // ❶ n 크기의 2차원 배열 생성
13 | int[][] snailArray = new int[n][n];
14 |
15 | int num = 1; // ❷ 달팽이 수열의 시작 숫자
16 |
17 | // ❸ 행과 열의 시작과 끝 인덱스를 설정
18 | int startRow = 0, endRow = n - 1;
19 | int startCol = 0, endCol = n - 1;
20 |
21 | while (startRow <= endRow && startCol <= endCol) {
22 | // ❹ 첫 번째 행 채우기
23 | for (int i = startCol; i <= endCol; i++) {
24 | snailArray[startRow][i] = num++;
25 | }
26 | startRow++;
27 |
28 | // ❺ 마지막 열 채우기
29 | for (int i = startRow; i <= endRow; i++) {
30 | snailArray[i][endCol] = num++;
31 | }
32 | endCol--;
33 |
34 | // ❻ 마지막 행 채우기
35 | if (startRow <= endRow) {
36 | for (int i = endCol; i >= startCol; i--) {
37 | snailArray[endRow][i] = num++;
38 | }
39 | endRow--;
40 | }
41 |
42 | // ❼ 첫 번째 열 채우기
43 | if (startCol <= endCol) {
44 | for (int i = endRow; i >= startRow; i--) {
45 | snailArray[i][startCol] = num++;
46 | }
47 | startCol++;
48 | }
49 | }
50 |
51 | return snailArray;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/solution/62.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int[] solution(String s) {
4 | // ❶ 이진 변환 횟수를 저장하는 변수
5 | int countTransform = 0;
6 | // ❷ 제거된 모든 0의 개수를 저장하는 변수
7 | int countZero = 0;
8 |
9 | // ❸ s가 '1'이 아닌 동안 계속 반복
10 | while (!s.equals("1")) {
11 | // ❹ 이진 변환 횟수를 1 증가
12 | countTransform++;
13 | // ❺ s에서 '0'의 개수를 세어 countZero에 누적
14 | int zero = s.replace("1", "").length();
15 | countZero += zero;
16 | // ❻ s에서 '1'의 개수를 세고, 이를 이진수로 반환
17 | // Integer.toBinaryString() 메소드를 활용
18 | s = Integer.toBinaryString(s.length() - zero);
19 | }
20 |
21 | // ❼ 이진 변환 횟수와 제거된 모든 '0'의 개수를 배열에 담아 반환
22 | return new int[]{countTransform, countZero};
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/solution/63.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 | import java.util.HashSet;
3 |
4 | public class Solution {
5 |
6 | public int solution(int[] topping) {
7 | // ❶ 결과값을 저장할 변수 초기화
8 | int answer = 0;
9 |
10 | // ❷ 토핑의 개수를 세어서 해시맵에 저장
11 | HashMap toppingMap = new HashMap<>();
12 | for (int t : topping) {
13 | toppingMap.put(t, toppingMap.getOrDefault(t, 0) + 1);
14 | }
15 |
16 | // ❸ 토핑의 종류를 저장할 해시셋
17 | HashSet toppingSet = new HashSet<>();
18 |
19 | // ❹ 롤케이크를 하나씩 해시셋에 넣으면서 확인
20 | for (int t : topping) {
21 | // ❺ 해시셋에 토핑을 추가하고, 해당 토핑의 전체 개수를 해시맵에서 줄임
22 | toppingSet.add(t);
23 | toppingMap.put(t, toppingMap.get(t) - 1);
24 |
25 | // ❻ 토핑의 전체 개수가 0이면 해시맵에서 제거
26 | if (toppingMap.get(t) == 0)
27 | toppingMap.remove(t);
28 |
29 | // ❼ 토핑의 종류의 수가 같다면
30 | if (toppingSet.size() == toppingMap.size())
31 | answer++;
32 | }
33 |
34 | // ❽ 공평하게 나눌 수 있는 방법의 수 반환
35 | return answer;
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/solution/64.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int[] solution(int brown, int yellow) {
4 | // ❶ 격자의 총 개수 (파란색 격자 + 흰색 격자)
5 | int totalSize = brown + yellow;
6 | // ❷ 세로 길이의 범위는 3부터 (갈색 격자 + 노란색 격자)의 제곱근
7 | int sqrt = (int)Math.sqrt(totalSize);
8 | for (int vertical = 3; vertical <= sqrt; vertical++) {
9 | // ❸ 사격형 구성이 되는지 확인
10 | if (totalSize % vertical == 0) {
11 | // ❹ 사각형의 가로 길이
12 | int horizontal = (int)(totalSize / vertical);
13 | // ❺ 카펫 형태로 만들 수 있는지 확인
14 | if (brown == (horizontal + vertical - 2) * 2) {
15 | return new int[]{horizontal, vertical}; // ❻ [가로 길이, 세로 길이]
16 | }
17 | }
18 | }
19 | return new int[]{}; // ❼ 만약 답을 찾지 못했다면 빈 리스트를 반환
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/solution/65.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int n) {
4 | return Integer.toBinaryString(n).replace("0","").length();
5 | }
6 |
7 | }
--------------------------------------------------------------------------------
/solution/66.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 |
3 | public class Solution {
4 |
5 | // ❶ 보드의 경계좌표를 벗어나는지 확인하는 메소드
6 | private static boolean isInBounds(int x, int y, int dx, int dy) {
7 | return Math.abs(x + dx) <= width && Math.abs(y + dy) <= height;
8 | }
9 |
10 | private static int width, height;
11 |
12 | public int[] solution(String[] keyinput, int[] board) {
13 | // ❷ 캐릭터의 초기 위치
14 | int x = 0, y = 0;
15 | // ❸ 각 방향에 대한 움직임
16 | HashMap moves = new HashMap<>();
17 | moves.put("up", new int[]{0, 1});
18 | moves.put("down", new int[]{0, -1});
19 | moves.put("left", new int[]{-1, 0});
20 | moves.put("right", new int[]{1, 0});
21 | // ❹ 게임 경계좌표
22 | width = board[0] / 2;
23 | height = board[1] / 2;
24 |
25 | for (String key : keyinput) {
26 | // ❺ 방향키에 따른 오프셋
27 | int dx = moves.get(key)[0];
28 | int dy = moves.get(key)[1];
29 | // ❻ 게임 맵의 크기를 벗어나지 않는지 확인
30 | if (isInBounds(x, y, dx, dy)) {
31 | x += dx;
32 | y += dy;
33 | }
34 | }
35 |
36 | // ❼ 캐릭터의 위치를 반환합니다.
37 | return new int[]{x, y};
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/solution/67.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public static void main(String[] args) {
4 | System.out.println(solution("ABCBDAB", "BDCAB"));
5 | System.out.println(solution("AGGTAB", "GXTXAYB"));
6 | }
7 |
8 | // 이 부분을 변경해서 실행해보세요.
9 | private static int solution(String str1, String str2) {
10 | // ❶ 두 문자열의 길이를 저장
11 | int m = str1.length();
12 | int n = str2.length();
13 |
14 | // ❷ LCS를 저장할 테이블 초기화
15 | int[][] dp = new int[m + 1][n + 1];
16 |
17 | // ❸ 동적 프로그래밍을 통해 LCS 길이 계산
18 | for (int i = 1; i <= m; i++) {
19 | for (int j = 1; j <= n; j++) {
20 | // ❹ 현재 비교하는 문자가 같으면
21 | if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
22 | dp[i][j] = dp[i - 1][j - 1] + 1;
23 | }
24 | // ❺ 현재 비교하는 문자가 같지 않으면
25 | else {
26 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
27 | }
28 | }
29 | }
30 |
31 | // ❻ LCS 길이 반환
32 | return dp[m][n];
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/solution/68.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | System.out.println(lis(new int[]{1, 4, 2, 3, 1, 5, 7, 3}));
7 | System.out.println(lis(new int[]{3, 2, 1}));
8 | }
9 |
10 | // 이 부분을 변경해서 실행해보세요.
11 | private static int lis(int[] nums) {
12 | int n = nums.length;
13 |
14 | // ❶ dp[i]는 nums[i]를 마지막으로 하는 LIS의 길이를 저장하는 배열입니다.
15 | int[] dp = new int[n];
16 | Arrays.fill(dp, 1);
17 |
18 | for (int i = 1; i < n; i++) {
19 | for (int j = 0; j < i; j++) {
20 | // ❷ num[i]와 nums[j]를 비교하여, nums[i]가 더 큰 경우에만 처리합니다.
21 | if (nums[i] > nums[j]) {
22 | // ❸ nums[i]를 이용하여 만든 부분 수열의 길이와
23 | // nums[j]를 이용하여 만든 부분 수열의 길이 + 1 중 최댓값을 저장합니다.
24 | dp[i] = Math.max(dp[i], dp[j] + 1);
25 | }
26 | }
27 | }
28 |
29 | // ❹ dp 배열에서 최댓값을 찾아 최장 증가 부분 수열의 길이를 반환합니다.
30 | return Arrays.stream(dp).max().getAsInt();
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/solution/69.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public static void main(String[] args) {
4 | int[][] arr1 = {{1, 3, 3, 2}, {2, 1, 4, 1}, {1, 5, 2, 3}};
5 | System.out.println(solution(arr1));
6 | int[][] arr2 = {{1, 7, 13, 2, 6}, {2, -4, 2, 5, 4}, {5, 3, 5, -3, 1}};
7 | System.out.println(solution(arr2));
8 | }
9 |
10 | // 이 부분을 변경해서 실행해보세요.
11 | private static int solution(int[][] arr) {
12 | // ❶ 입력 배열의 열의 개수를 저장합니다.
13 | int n = arr[0].length;
14 | // ❷ dp 배열을 초기화합니다. 4행 n열의 2차원 배열입니다.
15 | int[][] dp = new int[4][n];
16 |
17 | // 각 열에서 선택 가능한 4가지 조약돌 배치 패턴에 대해 첫 번째 열의 가중치를 초기화합니다.
18 | // ❸ 0: 상단, 1: 중앙, 2: 하단, 3: 상단과 하단
19 | dp[0][0] = arr[0][0];
20 | dp[1][0] = arr[1][0];
21 | dp[2][0] = arr[2][0];
22 | dp[3][0] = arr[0][0] + arr[2][0];
23 |
24 | // ❹ 두 번째 열부터 마지막 열까지 각 열에서 선택 가능한 4가지 조약돌 배치 패턴에 대해
25 | // 최대 가중치를 계산합니다.
26 | for (int i = 1; i < n; i++) {
27 | // 패턴 0이 선택된 경우, 이전은 패턴 {1, 2} 가능
28 | dp[0][i] = arr[0][i] + Math.max(dp[1][i - 1], dp[2][i - 1]);
29 | // 패턴 1이 선택된 경우, 이전은 패턴 {0, 2, 3} 가능
30 | dp[1][i] = arr[1][i] + Math.max(dp[0][i - 1], Math.max(dp[2][i - 1], dp[3][i - 1]));
31 | // 패턴 2이 선택된 경우, 이전은 패턴 {0, 1} 가능
32 | dp[2][i] = arr[2][i] + Math.max(dp[0][i - 1], dp[1][i - 1]);
33 | // 패턴 3이 선택된 경우, 이전은 패턴 {1} 가능
34 | dp[3][i] = arr[0][i] + arr[2][i] + dp[1][i - 1];
35 | }
36 |
37 | // ❺ 마지막 열에서 선택 가능한 4가지 조약돌 배치 패턴 중 최대 가중치를 반환합니다.
38 | return Math.max(Math.max(dp[0][n - 1], dp[1][n - 1]), Math.max(dp[2][n - 1], dp[3][n - 1]));
39 | }
40 |
41 | }
--------------------------------------------------------------------------------
/solution/70.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int n) {
4 | int[] fibo = new int[n + 1];
5 | fibo[0] = 0;
6 | fibo[1] = 1;
7 | for (int i = 2; i <= n; i++) {
8 | fibo[i] = (fibo[i - 1] + fibo[i - 2]) % 1234567;
9 | }
10 | return fibo[n];
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/solution/71.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int n) {
4 | // ❶ 동적 계획법을 위한 배열 초기화
5 | // dp[i]는 가로 길이가 i일 때 바닥을 채우는 방법의 수
6 | int[] dp = new int[n + 1];
7 | dp[1] = 1;
8 | dp[2] = 2;
9 |
10 | // ❷ 가로 길이가 3부터 n까지의 각각의 경우에 대해 바닥을 채우는 방법의 수를 구함
11 | for (int i = 3; i <= n; i++) {
12 | // ❸ dp[i]는 dp[i - 1]과 dp[i - 2]를 더한 값
13 | dp[i] = (dp[i - 1] + dp[i - 2]) % 1_000_000_007;
14 | }
15 | // ❹ 바닥의 가로 길이가 n일 때 바닥을 채우는 바업의 수인 dp[n]을 반환
16 | return dp[n];
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/solution/72.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int[][] triangle) {
4 | int n = triangle.length;
5 | int[][] dp = new int[n][n]; // ❶ dp 배열 초기화
6 |
7 | // ❷ dp 배열의 맨 아래쪽 라인 초기화
8 | for (int i = 0; i < n; i++) {
9 | dp[n - 1][i] = triangle[n - 1][i];
10 | }
11 |
12 | // ❸ 아래쪽 라인부터 올라가면서 dp 배열 채우기
13 | for (int i = n - 2; i >= 0; i--) {
14 | for (int j = 0; j <= i; j++) {
15 | dp[i][j] = Math.max(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j];
16 | }
17 | }
18 |
19 | return dp[0][0]; // 꼭대기에서의 최댓값 반환
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/solution/73.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | int solution(int[][] land) {
6 | // ❶ 각 행마다 이전 행에서의 최대 점수를 더해가며 최대 점수를 구합니다.
7 | for (int i = 1; i < land.length; i++) {
8 | for (int j = 0; j < 4; j++) {
9 | // ❷ 이전 행에서 현재 열의 값을 제외한 나머지 열들 중에서 가장 큰 값을 더해줍니다.
10 | int max = 0;
11 | for (int k = 0; k < 4; k++) {
12 | if (j != k) max = Math.max(max, land[i - 1][k]);
13 | }
14 | land[i][j] += max;
15 | }
16 | }
17 |
18 | return Arrays.stream(land[land.length - 1]).max().getAsInt();
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/solution/74.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int[] money) {
4 | // ❶ 점화식에 필요한 변수를 초기화
5 | int n = money.length;
6 | int[] dp1 = new int[n];
7 | int[] dp2 = new int[n];
8 |
9 | // ❷ 첫 번째 집을 도둑질하는 경우
10 | dp1[0] = money[0];
11 | dp1[1] = money[0];
12 | for (int i = 2; i < n - 1; i++) {
13 | dp1[i] = Math.max(dp1[i - 1], dp1[i - 2] + money[i]);
14 | }
15 |
16 | // ❸ 첫 번째 집을 도둑질하지 않는 경우
17 | dp2[1] = money[1];
18 | for (int i = 2; i < n; i++) {
19 | dp2[i] = Math.max(dp2[i - 1], dp2[i - 2] + money[i]);
20 | }
21 |
22 | // ❹ 두 경우 중 최댓값 찾기
23 | return Math.max(dp1[n - 2], dp2[n - 1]);
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/solution/75.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int [][]board) {
4 | // ❶ 주어진 2차원 보드의 행과 열의 개수를 변수에 저장합니다.
5 | int row = board.length;
6 | int col = board[0].length;
7 |
8 | // ❷ 각 행과 열을 순회하며 최적의 정사각형을 찾습니다.
9 | for (int i = 1; i < row; i++) {
10 | for (int j = 1; j < col; j++) {
11 | // ❸ 현재 위치의 값이 1인 경우를 확인합니다.
12 | if (board[i][j] == 1) {
13 | // ❹ 현재 위치에서 위, 왼쪽, 대각선 왼쪽 위의 값들을 가져옵니다.
14 | int up = board[i - 1][j];
15 | int left = board[i][j - 1];
16 | int upLeft = board[i - 1][j - 1];
17 | // ❺ 현재 위치의 값을 이전 위치들의 값들 중
18 | // 가장 작은 값에 1을 더한 값으로 업데이트 합니다.
19 | board[i][j] += Math.min(up, Math.min(upLeft, left));
20 | }
21 | }
22 | }
23 |
24 | int answer = 0;
25 | // ❻ 보드에서 가장 큰 값(최대 정사각형의 한 변의 길이)을 찾습니다.
26 | for (int i = 0; i < row; i++) {
27 | for (int j = 0; j < col; j++) {
28 | answer = Math.max(answer, board[i][j]);
29 | }
30 | }
31 |
32 | // ❼ 최대 정사각형의 넓이를 반환합니다.
33 | return answer * answer;
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/solution/76.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 | import java.util.HashSet;
3 |
4 | public class Solution {
5 |
6 | private static final int INF = 20_001;
7 |
8 | public int solution(String[] strs, String t) {
9 | int n = t.length(); // ❶ 타겟 문자열 t의 길이
10 | // ❷ 각 위치에서 필요한 최소 조각수를 저장할 배열(초기값은 INF로 함)
11 | int[] dp = new int[n + 1];
12 | Arrays.fill(dp, INF);
13 | // ❸ 빈 문자열을 위해 필요한 최소 조각수는 0
14 | dp[0] = 0;
15 |
16 | // ❹ strs 조각들의 길이를 저장한 해시셋
17 | HashSet sizes = new HashSet<>();
18 | for (String str : strs) {
19 | sizes.add(str.length());
20 | }
21 |
22 | // ❺ dp[i]부터 dp[n]까지 채우기 위한 반복문
23 | for (int i = 1; i <= n; i++) {
24 | // ❻ 각 str 조각의 문자열 길이에 대하여
25 | for (int size : sizes) {
26 | if (i - size >= 0) {
27 | int idx = i;
28 | String sub = t.substring(idx - size, idx);
29 | // ❼ 이미 구한 해와 strs 조각을 추가해서 문자열을 만들 수 있다면
30 | if (Arrays.asList(strs).contains(sub)) {
31 | // ❽ 해당 위치의 최소 조각수를 갱신
32 | dp[i] = Math.min(dp[i], dp[i - size] + 1);
33 | }
34 | }
35 | }
36 | }
37 |
38 | // ❾ 최소 조각수를 반환
39 | return dp[n] < INF ? dp[n] : -1;
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/solution/77.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Arrays;
3 |
4 | public class Solution {
5 |
6 | public static void main(String[] args) {
7 | System.out.println(Arrays.toString(solution(123)));
8 | System.out.println(Arrays.toString(solution(350)));
9 | }
10 |
11 | // 이 부분을 변경해서 실행해보세요.
12 | private static int[] solution(int amount) {
13 | // ❶ 화폐 단위를 큰 순서대로 정렬해서 저장
14 | int[] denominations = {100, 50, 10, 1};
15 |
16 | // ❷ 거스름돈을 담을 리스트
17 | ArrayList change = new ArrayList<>();
18 |
19 | for (int coin : denominations) {
20 | // ❸ 해당 화폐 단위로 거스름돈을 계속 나눠줌
21 | while (amount >= coin) {
22 | change.add(coin); // ❹ 거스름돈 리스트 업데이트
23 | amount -= coin; // ❺ 정산이 완료된 거스름돈 뺌
24 | }
25 | }
26 | // ❻ 거스름돈 리스트를 배열로 변경하여 반환
27 | return change.stream().mapToInt(Integer::intValue).toArray();
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/solution/78.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public static void main(String[] args) {
6 | int[][] items1 = {{10, 19}, {7, 10}, {6, 10}};
7 | System.out.println(solution(items1, 15));
8 | int[][] items2 = {{10, 60}, {20, 100}, {30, 120}};
9 | System.out.println(solution(items2, 50));
10 | }
11 |
12 | private static class Item {
13 | int value, weight;
14 | double valuePerWeight;
15 |
16 | public Item(int value, int weight, double valuePerWeight) {
17 | this.value = value;
18 | this.weight = weight;
19 | this.valuePerWeight = valuePerWeight;
20 | }
21 | }
22 |
23 | // 이 부분을 변경해서 실행해보세요.
24 | private static double solution(int[][] items, int weight_limit) {
25 | // ❶ 각 물건의 단위 무게당 가치를 계산하여 item 배열에 추가
26 | Item[] item = new Item[items.length];
27 | for (int i = 0; i < items.length; i++) {
28 | item[i] = new Item(items[i][1], items[i][0],(double)items[i][1] / items[i][0]);
29 | }
30 |
31 | // ❷ 단위 무게당 가치가 높은 순으로 물건을 정렬
32 | Arrays.sort(item, (o1, o2) -> Double.compare(o2.valuePerWeight, o1.valuePerWeight));
33 |
34 | double totalValue = 0; // ❸ 선택한 물건들의 총 가치를 저장하는 변수
35 | int remainingWeight = weight_limit; // ❹ 남은 무게 한도를 저장하는 변수
36 |
37 | // ❺ 물건을 선택합니다.
38 | for (Item i : item) {
39 | if (i.weight <= remainingWeight) {
40 | // ❻ 남은 무게 한도 내에서 물건을 통째로 선택
41 | totalValue += i.value;
42 | remainingWeight -= i.weight;
43 | }
44 | else {
45 | // ❼ 남은 무게 한도가 물건의 무게보다 작으면 쪼개서 일부분만 선택
46 | double fraction = (double) remainingWeight / i.weight;
47 | totalValue += i.value * fraction;
48 | break; // ❽ 이미 배낭의 무게 한도를 모두 사용한 경우
49 | }
50 | }
51 |
52 | return totalValue;
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/solution/79.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public int solution(int[] d, int budget) {
6 | Arrays.sort(d); // ❶ 배열 d를 오름차순으로 정렬
7 | int count = 0; // ❷ 지원할 수 있는 부서의 개수를 세는 변수
8 |
9 | for (int amount : d) {
10 | if (budget < amount) {
11 | break; // ❸ 남은 예산이 신청한 금액보다 작으면 더 이상 지원할 수 없으므로 종료
12 | }
13 | budget -= amount; // ❹ 예산에서 신청한 금액을 차감
14 | count++;
15 | }
16 |
17 | return budget >= 0 ? count : count - 1;
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/solution/80.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | public class Solution {
4 |
5 | public int solution(int[] people, int limit) {
6 | Arrays.sort(people); // ❶ 몸무게를 오름차순으로 정렬
7 | int count = 0; // ❷ 필요한 보트 개수
8 | int i = 0; // ❸ 가장 가벼운 사람을 가리키는 인덱스
9 | int j = people.length - 1; // ❹ 가장 무거운 사람을 가르키는 인덱스
10 |
11 |
12 | while (i <= j) {
13 | // ❺ 가장 무거운 사람과 가장 가벼운 사람을 같이 태울 수 있으면 두 사람 모두 보트에 태움
14 | if (people[i] + people[j] <= limit) {
15 | i += 1;
16 | }
17 | // ❻ 무거운 사람만 태울 수 있으면 무거운 사람만 보트에 태움
18 | j -= 1;
19 | count += 1;
20 | }
21 |
22 | return count;
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/solution/81.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Collections;
3 | import java.util.HashMap;
4 |
5 | public class Solution {
6 |
7 | public int solution(int k, int[] tangerine) {
8 | // ❶ 귤의 개수를 세는 HashMap 객체 생성
9 | HashMap map = new HashMap<>();
10 | for (int i : tangerine) {
11 | map.put(i, map.getOrDefault(i, 0) + 1);
12 | }
13 |
14 | // ❷ 개수를 내림차순으로 정렬
15 | ArrayList sortedCounts = new ArrayList<>(map.values());
16 | sortedCounts.sort(Collections.reverseOrder());
17 |
18 | int numTypes = 0; // ❸ 현재까지의 종류 수
19 | int countSum = 0; // ❹ 현재까지의 귤 개수 합
20 |
21 | for (int count : sortedCounts) {
22 | countSum += count;
23 | numTypes++;
24 |
25 | // ❺ 귤 개수 합이 k 이상이 되는 순간 종료
26 | if (countSum >= k)
27 | break;
28 | }
29 |
30 | return numTypes;
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/solution/82.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public int solution(int n, int[] stations, int w) {
4 | int answer = 0;
5 | int location = 1; // ❶ 현재 탐색하는 아파트의 위치
6 | int idx = 0; // ❷ 설치된 기지국의 인덱스
7 |
8 | while (location <= n) {
9 | // ❸ 기지국이 설치된 위치에 도달한 경우
10 | if (idx < stations.length && location >= stations[idx] - w) {
11 | location = stations[idx] + w + 1;
12 | idx++;
13 | }
14 | // ❹ 기지국이 설치되지 않은 위치인 경우
15 | else {
16 | location += 2 * w + 1; // ❺ 기지국을 설치하고 해당 범위를 넘어감
17 | answer++;
18 | }
19 | }
20 |
21 | return answer;
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/solution/83.java:
--------------------------------------------------------------------------------
1 | public class Solution {
2 |
3 | public static void main(String[] args) {
4 | System.out.println(solution(3,4,2,3,3 ,1,5));
5 | System.out.println(solution(2,2,1,1,2 ,2,2));
6 | System.out.println(solution(3,3,1,2,3 ,3,4));
7 | }
8 |
9 | public static String solution(int n, int m, int x, int y, int r, int c, int k) {
10 | StringBuilder sb = new StringBuilder();
11 |
12 | int dist = k - (Math.abs(x - r) + Math.abs(y - c));
13 |
14 | if (dist < 0 || dist % 2 == 1) {
15 | return "impossible";
16 | }
17 |
18 | while (k-- > 0) {
19 | int[] next = getNext(n, m, x, y, r, c, k);
20 | x = x + next[0];
21 | y = y + next[1];
22 | sb.append((char)next[2]);
23 | }
24 |
25 | return sb.toString();
26 | }
27 |
28 | // 아래 > 왼쪽 > 오른쪽 > 위쪽
29 | private static int[] getNext(int n, int m, int x, int y, int r, int c, int k) {
30 | if (x + 1 <= n && Math.abs(x + 1 - r) + Math.abs(y - c) <= k) {
31 | return new int[]{1, 0, 'd'};
32 | }
33 | else if (y - 1 >= 1 && Math.abs(x - r) + Math.abs(y - 1 - c) <= k) {
34 | return new int[]{0, -1, 'l'};
35 | }
36 | else if (y + 1 <= m && Math.abs(x - r) + Math.abs(y + 1 - c) <= k) {
37 | return new int[]{0, 1, 'r'};
38 | }
39 | else {
40 | return new int[]{-1, 0, 'u'};
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/solution/84.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 |
3 | public static void main(String[] args) {
4 | System.out.println(solution(4, 1, new int[]{0}, new int[]{0}));
5 | }
6 |
7 | public static long solution(int cap, int n, int[] deliveries, int[] pickups) {
8 | int deliveries_idx = n - 1;
9 | int pickups_idx = n - 1;
10 |
11 | while (deliveries_idx >= 0 && deliveries[deliveries_idx] == 0) {
12 | deliveries_idx--;
13 | }
14 | while (pickups_idx >= 0 && pickups[pickups_idx] == 0) {
15 | pickups_idx--;
16 | }
17 |
18 | long answer = 0;
19 |
20 | while (deliveries_idx >= 0 || pickups_idx >= 0) {
21 | answer += (Math.max(deliveries_idx, pickups_idx) + 1) * 2L;
22 | deliveries_idx = getMaxIdx(cap, deliveries, deliveries_idx);
23 | pickups_idx = getMaxIdx(cap, pickups, pickups_idx);
24 | }
25 |
26 | return answer;
27 | }
28 |
29 | private static int getMaxIdx(int cap, int[] target, int idx) {
30 | while (idx >= 0 && (cap > 0 || target[idx] == 0)) {
31 | if (target[idx] > cap) {
32 | target[idx] -= cap;
33 | cap = 0;
34 | }
35 | else {
36 | cap -= target[idx];
37 | target[idx] = 0;
38 | idx--;
39 | }
40 | }
41 | return idx;
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/solution/85.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.HashMap;
3 | import java.util.StringTokenizer;
4 |
5 | class Solution {
6 |
7 | private static final int MONTH_OF_YEAR = 12;
8 | private static final int DAY_OF_MONTH = 28;
9 |
10 | public int[] solution(String today, String[] terms, String[] privacies) {
11 | int todayDay = stringToDay(today);
12 |
13 | HashMap term = new HashMap<>();
14 | for (String s : terms) {
15 | StringTokenizer st = new StringTokenizer(s);
16 | term.put(st.nextToken().charAt(0), Integer.parseInt(st.nextToken()) * DAY_OF_MONTH);
17 | }
18 |
19 | ArrayList answer = new ArrayList<>();
20 |
21 | for (int i = 1; i <= privacies.length; i++) {
22 | StringTokenizer st = new StringTokenizer(privacies[i - 1]);
23 | int day = stringToDay(st.nextToken()) + term.get(st.nextToken().charAt(0));
24 | if (todayDay >= day) {
25 | answer.add(i);
26 | }
27 | }
28 |
29 | return answer.stream().mapToInt(i -> i).toArray();
30 | }
31 |
32 | private static int stringToDay(String s) {
33 | StringTokenizer st = new StringTokenizer(s, ".");
34 | int month = (Integer.parseInt(st.nextToken()) - 2000) * MONTH_OF_YEAR + Integer.parseInt(st.nextToken()) - 1;
35 | int day = Integer.parseInt(st.nextToken());
36 | return month * DAY_OF_MONTH + day;
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/solution/86.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 | import java.util.Arrays;
3 |
4 | class Solution {
5 |
6 | public static void main(String[] args) {
7 | System.out.println(Arrays.toString(solution(new String[]{"1110","100111100","0111111010"})));
8 | System.out.println(Arrays.toString(solution(new String[]{"1011110","01110","101101111010"})));
9 | System.out.println(Arrays.toString(solution(new String[]{"1100111011101001"})));
10 | }
11 |
12 | public static String[] solution(String[] s) {
13 | String[] answer = new String[s.length];
14 |
15 | for (int i = 0; i < s.length; i++) {
16 | StringBuilder start = new StringBuilder();
17 | ArrayDeque stack = new ArrayDeque<>();
18 | char[] end = s[i].toCharArray();
19 |
20 | for (char c : end) {
21 | stack.push(c);
22 | if (stack.size() >= 3) {
23 | char s3 = stack.pop();
24 | char s2 = stack.pop();
25 | char s1 = stack.pop();
26 | if (("" + s1 + s2 + s3).equals("110")) {
27 | start.append("110");
28 | }
29 | else {
30 | stack.push(s1);
31 | stack.push(s2);
32 | stack.push(s3);
33 | }
34 | }
35 | }
36 |
37 | StringBuilder ans = new StringBuilder();
38 | while (!stack.isEmpty()) {
39 | ans.append(stack.pollLast());
40 | }
41 |
42 | if (ans.indexOf("11") >= 0) {
43 | ans.insert(ans.indexOf("11"), start);
44 | }
45 | else if (ans.lastIndexOf("0") >= 0) {
46 | ans.insert(ans.lastIndexOf("0") + 1, start);
47 | }
48 | else {
49 | ans.insert(0, start);
50 | }
51 |
52 | answer[i] = ans.toString();
53 | }
54 |
55 | return answer;
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/solution/87.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | class Solution {
4 |
5 | public static void main(String[] args) {
6 | int[][] a1 = {{1, 1, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 1}, {1, 1, 1, 1}};
7 | System.out.println(Arrays.toString(solution(a1)));
8 | int[][] a2 = {{1, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 1, 1, 1, 1}, {0, 1, 0, 0, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 1, 0, 0, 1}, {0, 0, 0, 0, 1, 1, 1, 1}};
9 | System.out.println(Arrays.toString(solution(a2)));
10 | }
11 |
12 | public static int[] solution(int[][] arr) {
13 | int[][] rev = new int[arr.length][arr.length];
14 | for (int i = 0; i < rev.length; i++) {
15 | rev[i] = arr[i].clone();
16 | for (int j = 0; j < rev.length; j++) {
17 | rev[i][j] ^= 1;
18 | }
19 | }
20 |
21 | Compression(arr);
22 | int one = sum(arr);
23 | Compression(rev);
24 | int zero = sum(rev);
25 |
26 | return new int[]{zero, one};
27 | }
28 |
29 | private static void Compression(int[][] arr) {
30 | for (int p = 0; Math.pow(2, p) < arr.length; p++) {
31 | int pow = (int)Math.pow(2, p);
32 | int quad = (int)Math.pow(4, p + 1);
33 | for (int i = (pow * 2) - 1; i < arr.length; i += (pow * 2)) {
34 | for (int j = (pow * 2) - 1; j < arr.length; j += (pow * 2)) {
35 | if (arr[i][j] + arr[i - pow][j] + arr[i][j - pow] + arr[i - pow][j - pow] == quad) {
36 | arr[i - pow][j] = arr[i][j - pow] = arr[i - pow][j - pow] = 0;
37 | arr[i][j] = quad;
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
44 | private static int sum(int[][] arr) {
45 | int sum = 0;
46 | for (int[] a : arr) {
47 | for (int x : a) {
48 | if (x > 0)
49 | sum++;
50 | }
51 | }
52 | return sum;
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/solution/88.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 | public int solution(int[] numbers) {
3 | int answer = 45;
4 | for (int n : numbers)
5 | answer -= n;
6 | return answer;
7 | }
8 | }
--------------------------------------------------------------------------------
/solution/89.java:
--------------------------------------------------------------------------------
1 | import java.util.HashSet;
2 | import java.util.regex.Pattern;
3 |
4 | class Solution {
5 |
6 | public static void main(String[] args) {
7 | String[] user_id_3 = {"frodo", "fradi", "crodo", "abc123", "frodoc"};
8 | String[] banned_id_3 = {"fr*d*", "*rodo", "******", "******"};
9 | System.out.println(solution(user_id_3, banned_id_3));
10 | }
11 |
12 | public static int solution(String[] user_id, String[] banned_id) {
13 | answer = new HashSet<>();
14 | userId = user_id;
15 | used = new boolean[banned_id.length];
16 | regex = new Pattern[banned_id.length];
17 |
18 | for (int i = 0; i < banned_id.length; i++) {
19 | regex[i] = Pattern.compile(banned_id[i].replace("*", "[a-z0-9]"));
20 | }
21 |
22 | backtrack(0, "");
23 |
24 | return answer.size();
25 | }
26 |
27 | private static String[] userId;
28 | private static Pattern[] regex;
29 | private static boolean[] used;
30 | private static HashSet answer;
31 |
32 | private static void backtrack(int idx, String users) {
33 | if (users.length() == regex.length) {
34 | answer.add(users);
35 | }
36 |
37 | for (int i = idx; i < userId.length; i++) {
38 | String id = userId[i];
39 | for (int j = 0; j < regex.length; j++) {
40 | if (!used[j] && regex[j].matcher(id).matches()) {
41 | used[j] = true;
42 | backtrack(i + 1, users + i);
43 | used[j] = false;
44 | }
45 | }
46 | }
47 | }
48 |
49 | }
--------------------------------------------------------------------------------
/solution/90.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 |
3 | public static void main(String[] args) {
4 | System.out.println(solution(437674, 3));
5 | System.out.println(solution(110011, 2));
6 | }
7 |
8 | public static int solution(int n, int k) {
9 | String[] p = Integer.toString(n, k).split("0");
10 | int answer = 0;
11 | for (String s : p) {
12 | if(!s.isEmpty() && isPrimeNumber(Long.parseLong(s)))
13 | answer++;
14 | }
15 | return answer;
16 | }
17 |
18 | private static boolean isPrimeNumber(long num) {
19 | if (num == 1) return false;
20 | boolean isPrime = true;
21 | int sqrt = (int)Math.sqrt(num + 1);
22 |
23 | for(int i = 2; i <= sqrt; i++) {
24 | if(num % i == 0) {
25 | isPrime = false;
26 | break;
27 | }
28 | }
29 |
30 | return isPrime;
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/solution/91.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 |
3 | private static int[] dx = {0, 0, 1, -1};
4 | private static int[] dy = {1, -1, 0, 0};
5 |
6 | public int[] solution(String[][] places) {
7 | int[] answer = {1, 1, 1, 1, 1};
8 |
9 | for (int t = 0; t < places.length; t++) {
10 | char[][] place = new char[5][5];
11 | for (int i = 0; i < 5; i++) {
12 | place[i] = places[t][i].toCharArray();
13 | }
14 |
15 | for (int i = 0; i < 5; i++) {
16 | for (int j = 0; j < 5; j++) {
17 | if (place[i][j] == 'P') {
18 | for (int k = 0; k < 4; k++) {
19 | int x = i + dx[k];
20 | int y = j + dy[k];
21 |
22 | if (x < 0 || x > 4 || y < 0 || y > 4)
23 | continue;
24 |
25 | if (place[x][y] == 'P' || place[x][y] == 'p')
26 | answer[t] = 0;
27 |
28 | if (place[x][y] == 'O')
29 | place[x][y] = 'p';
30 | }
31 | }
32 | }
33 | }
34 |
35 | }
36 |
37 | return answer;
38 | }
39 | }
--------------------------------------------------------------------------------
/solution/92.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 |
3 | public static void main(String[] args) {
4 | System.out.println(solution(10, 10, new int[][]{{10,15,2,1,2},{20,20,3,3,4}}));
5 | }
6 |
7 | public static int solution(int alp, int cop, int[][] problems) {
8 | int maxAlp = 0;
9 | int maxCop = 0;
10 |
11 | for (int[] problem : problems) {
12 | maxAlp = Math.max(maxAlp, problem[0]);
13 | maxCop = Math.max(maxCop, problem[1]);
14 | }
15 |
16 | int[][] dp = new int[maxAlp + 2][maxCop + 2];
17 |
18 | for (int i = 0; i <= maxAlp; i++) {
19 | for (int j = 0; j <= maxCop; j++) {
20 | dp[i][j] = Math.max(i - alp, 0) + Math.max(j - cop, 0);
21 | }
22 | }
23 |
24 | for (int i = 0; i <= maxAlp; i++) {
25 | for (int j = 0; j <= maxCop; j++) {
26 | for (int[] problem : problems) {
27 | if (problem[0] > i || problem[1] > j)
28 | continue;
29 | int x = Math.min(i + problem[2], maxAlp);
30 | int y = Math.min(j + problem[3], maxCop);
31 | dp[x][y] = Math.min(dp[x][y], dp[i][j] + problem[4]);
32 | }
33 |
34 | dp[i + 1][j] = Math.min(dp[i + 1][j], dp[i][j] + 1);
35 | dp[i][j + 1] = Math.min(dp[i][j + 1], dp[i][j] + 1);
36 | }
37 | }
38 |
39 | return dp[maxAlp][maxCop];
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/solution/93.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayDeque;
2 |
3 | class Solution {
4 |
5 | public int solution(int[] queue1, int[] queue2) {
6 | long sum1 = 0, sum2 = 0;
7 | ArrayDeque queue = new ArrayDeque<>();
8 |
9 | for (int i : queue1) {
10 | queue.add(i);
11 | sum1 += i;
12 | }
13 |
14 | for (int i : queue2) {
15 | sum2 += i;
16 | }
17 |
18 | long target = (sum1 + sum2) / 2;
19 |
20 | int q2 = 0;
21 |
22 | int count = 0;
23 |
24 | while (!queue.isEmpty() && q2 < queue2.length) {
25 | if (sum1 == target)
26 | break;
27 |
28 | if (sum1 < target) {
29 | queue.add(queue2[q2]);
30 | sum1 += queue2[q2];
31 | q2++;
32 | }
33 | else {
34 | sum1 -= queue.poll();
35 | }
36 |
37 | count++;
38 | }
39 |
40 | if (sum1 != target)
41 | return -1;
42 |
43 | return count;
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/solution/94.java:
--------------------------------------------------------------------------------
1 | import java.util.Arrays;
2 |
3 | class Solution {
4 |
5 | public int solution(int[] A, int[] B) {
6 | Arrays.sort(A);
7 | Arrays.sort(B);
8 |
9 | int l = B.length - 1;
10 | int answer = 0;
11 |
12 | for (int i = A.length - 1; i >= 0; i--) {
13 | if (A[i] < B[l]) {
14 | l--;
15 | answer++;
16 | }
17 | }
18 |
19 | return answer;
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/solution/95.java:
--------------------------------------------------------------------------------
1 | import java.util.HashMap;
2 | import java.util.Optional;
3 |
4 | class Solution {
5 |
6 | public int[] solution(String[] gems) {
7 | HashMap map = new HashMap<>();
8 | for (String gem : gems) map.put(gem, 0);
9 |
10 | int l = 0, r = 0, min = gems.length + 1, al = 1, ar = gems.length, max = map.size();
11 | map = new HashMap<>();
12 |
13 | while (r < gems.length) {
14 | int cnt = Optional.ofNullable(map.get(gems[r])).orElse(0) + 1;
15 | map.put(gems[r++], cnt);
16 |
17 | while (map.size() == max) {
18 | if (min > r - l) {
19 | min = r - l;
20 | al = l + 1;
21 | ar = r;
22 | }
23 | cnt = map.get(gems[l]) - 1;
24 | if(cnt == 0) map.remove(gems[l]);
25 | else map.put(gems[l], cnt);
26 | l++;
27 | }
28 | }
29 |
30 | return new int[]{al, ar};
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/solution/96.java:
--------------------------------------------------------------------------------
1 | class Solution {
2 |
3 | public static void main(String[] args) {
4 | int[][] board2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
5 | int[][] skill2 = {{1, 1, 1, 2, 2, 4}, {1, 0, 0, 1, 1, 2}, {2, 2, 0, 2, 0, 100}};
6 | System.out.println(solution(board2, skill2));
7 | }
8 |
9 | public static int solution(int[][] board, int[][] skill) {
10 | int[][] sum = new int[board.length + 1][board[0].length + 1];
11 |
12 | for (int[] s : skill) {
13 | int degree = s[5] * (s[0] == 1 ? -1 : 1);
14 | sum[s[1]][s[2]] += degree;
15 | sum[s[3] + 1][s[4] + 1] += degree;
16 | sum[s[1]][s[4] + 1] -= degree;
17 | sum[s[3] + 1][s[2]] -= degree;
18 | }
19 |
20 | for (int i = 0; i < sum.length; i++) {
21 | for (int j = 1; j < sum[0].length; j++) {
22 | sum[i][j] += sum[i][j - 1];
23 | }
24 | }
25 |
26 | for (int i = 1; i < sum.length; i++) {
27 | for (int j = 0; j < sum[0].length; j++) {
28 | sum[i][j] += sum[i - 1][j];
29 | }
30 | }
31 |
32 | int answer = 0;
33 |
34 | for (int i = 0; i < board.length; i++) {
35 | for (int j = 0; j < board[0].length; j++) {
36 | if (board[i][j] + sum[i][j] > 0)
37 | answer++;
38 | }
39 | }
40 |
41 | return answer;
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/solution/97.java:
--------------------------------------------------------------------------------
1 | import java.util.HashSet;
2 |
3 | class Solution {
4 | public int[] solution(int[] lottos, int[] win_nums) {
5 | HashSet win = new HashSet<>();
6 | for (int winNum : win_nums) {
7 | win.add(winNum);
8 | }
9 |
10 | int zero = 0, match = 0;
11 |
12 | for (int lotto : lottos) {
13 | if (lotto == 0) zero++;
14 | else if (win.contains(lotto)) match++;
15 | }
16 |
17 | return new int[]{7 - Math.max((match + zero), 1), 7 - Math.max(match, 1)};
18 | }
19 | }
--------------------------------------------------------------------------------