diff --git a/.gitignore b/.gitignore index a4aa106..2051fc6 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ out/* .idea/dictionaries .idea/libraries .idea/caches + +src/dami/codingtest diff --git a/README.md b/README.md index 403bc1f..c9af875 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,6 @@ --- -## 2018.05.13 -### 코드 공유를 위한 Github 환경설정 -* A+B 출력 문제를 통한 환경설정 Test - * [https://www.acmicpc.net/problem/1000](https://www.acmicpc.net/problem/1000) - -## 2018.05.20 ### 정렬 :heavy_check_mark: [issue 정리 내용](/contents/180520.md) * [#issue1] Comparable, Comparator 을 이용한 Java 객체 정렬 @@ -66,7 +60,6 @@ * [#issue10-1] 문자열 분리를 위한 StringTokenizer와 String.spilt의 사용 예제 * [#issue11] BufferedReader/Scanner, Arrays.sort()/Collections.sort()에 따른 시간복잡도 분석 -## 2018.05.27 ### 수학1-1(나머지, 최대공약수, 최소공배수, GCD의 합, 진법) :heavy_check_mark: [issue 정리 내용](/contents/180527.md) * [#issue1] 최대공약수(GCD)를 구하는 방법 '유클리드 호제법'의 개념 @@ -74,13 +67,11 @@ * [#issue2] 기본적인 아스키코드 * [#issue3] 10진수 <-> 2진수, 8진수, 16진수 변환 시 Integer API 사용 -## 2018.06.03 ### 수학1-2(소수, 소인수분해, 팩토리얼) :heavy_check_mark: [issue 정리 내용](/contents/180603.md) * [#issue1] 1~N 까지의 수에서 모든 소수를 구하는 방법 '에라토스테네스의 체'의 개념 * [#issue2] 소인수분해의 개념과 간단한 풀이법 -## 2018.06.10 ### 수학2-1(제곱, 행렬, 피보나치의 수, 이항계수, 파스칼의 삼각형) :heavy_check_mark: [issue 정리 내용](/contents/180610.md) * [#issue1] 분할정복을 이용하여 제곱을 구하는 방법 @@ -90,7 +81,6 @@ * [#issue5] 음수 번째의 피보나치의 수에 대한 규칙성 * [#issue6] 이항계수 구하는 방법 -## 2018.06.17 ### 수학2-2(카탈란 수, 오일러 피 함수, 유클리드 알고리즘, 나머지 연산, 순열) :heavy_check_mark: [issue 정리 내용](/contents/180617.md) * [#issue1] 카탈란 수의 개념과 적용 사례 @@ -99,7 +89,6 @@ * [#issue2-1] 오일러 피 함수 구하는 방법 * [#issue3] 사전순으로 다음에 오는 순열 -## 2018.06.24 ### 자료구조1(스택, 큐, 덱, 문자열) :heavy_check_mark: [issue 정리 내용](/contents/180624.md) * [#issue1] 스택(Stack)의 개념 @@ -111,7 +100,6 @@ * [#issue4] String indexOf()의 사용법 * [#issue5] String substring()의 사용법 -## 2018.07.01 ### 자료구조2(스택, Disjoint-set, 비트마스크, 힙, 이진 탐색 트리) :heavy_check_mark: [issue 정리 내용](/contents/180701.md) * [#issue1] Disjoint-set(서로소 집합 자료구조)의 개념과 사용 예제 @@ -123,8 +111,6 @@ * [#issue4] 최대힙의 삽입과 삭제 * [#issue5] 이진 탐색 트리의 개념 - -## 2018.07.08 ### 트리와 이진 탐색 :heavy_check_mark: [issue 정리 내용](/contents/180708.md) * [#issue1] 트리의 개념과 적용 사례 @@ -133,8 +119,6 @@ * [#issue1-3] 이진 트리의 순회(전위, 중위, 후위 순회) * [#issue2] 이진 탐색의 개념 - -## 2018.07.15 ### 그래프1(그래프, DFS, BFS, 이분그래프, 사이클, 플러드 필) :heavy_check_mark: [issue 정리 내용](/contents/180715.md) * [#issue1] 그래프의 개념과 적용 사례 @@ -145,7 +129,6 @@ * [#issue5] 사이클의 개념 * [#issue6] 플러드 필(Flood Fill) 알고리즘의 개념 -## 2018.08.26 ### 그래프2(DAG(Directed Acyclic Graph), 위상 정렬, 최소 비용 신장 트리(Minimum Spanning Tree), Prim, Kruskal, 최단 경로(Shortest Path), Bellman-Ford) :heavy_check_mark: [issue 정리 내용](/contents/180826.md) * [#issue1] DAG(Directed Acyclic Graph)의 개념 @@ -156,46 +139,9 @@ * [#issue4] 최단 경로(Shortest Path) * [#issue4-1] Bellman-Ford 알고리즘 -## 2018.09.02 ### 그래프2(다익스트라(Dijkstra), 플로이드(Floyd-Warshall), SPFA(Shortest Path Faster)) :heavy_check_mark: [issue 정리 내용](/contents/180902.md) * [#issue1] -## 2018.09.16 -### 삼성 SW 역량 테스트 기출 문제 (1) -:heavy_check_mark: [issue 정리 내용](/contents/180916.md) -* [#issue1] 치킨 배달 -* [#issue2] 드래곤 커브 -* [#issue3] 사다리 조작 -* [#issue4] 감시 - - -## 2018.09.23 -### 삼성 SW 역량 테스트 기출 문제 (2) -:heavy_check_mark: [issue 정리 내용](/contents/180923.md) -* [#issue1] 톱니바퀴 -* [#issue2] 경사로 -* [#issue3] 스타트와 링크 -* [#issue4] 연산자 끼워넣기 -* [#issue5] 로봇 청소기 -* [#issue6] 연구소 - - -## 2018.09.30 -### 삼성 SW 역량 테스트 기출 문제 (3) -:heavy_check_mark: [issue 정리 내용](/contents/180930.md) -* [#issue1] 퇴사 -* [#issue2] 테트로미노 -* [#issue3] 주사위 굴리기 -* [#issue4] 시험 감독 -* [#issue5] 뱀 -* [#issue6] 구슬 탈출 2 - - -## 2018.10.28 -### 삼성 SW 역량 테스트 기출 문제 (4) -:heavy_check_mark: [issue 정리 내용](/contents/181028.md) -* [#issue1] 큐빙 -* [#issue2] 인구 이동 -* [#issue3] 나무 재테크 -* [#issue4] 아기 상어 \ No newline at end of file +### 삼성 SW 역량 테스트 +:heavy_check_mark: [기출 문제 정리 내용](/contents/samsung/README.md) diff --git a/contents/180916.md b/contents/samsung/180916.md similarity index 100% rename from contents/180916.md rename to contents/samsung/180916.md diff --git a/contents/180923.md b/contents/samsung/180923.md similarity index 100% rename from contents/180923.md rename to contents/samsung/180923.md diff --git a/contents/180930.md b/contents/samsung/180930.md similarity index 100% rename from contents/180930.md rename to contents/samsung/180930.md diff --git a/contents/181028.md b/contents/samsung/181028.md similarity index 100% rename from contents/181028.md rename to contents/samsung/181028.md diff --git a/contents/samsung/README.md b/contents/samsung/README.md new file mode 100644 index 0000000..7192073 --- /dev/null +++ b/contents/samsung/README.md @@ -0,0 +1,33 @@ +## 삼성 SW 역량 테스트 + +### 기출 문제 (1) +:heavy_check_mark: [issue 정리 내용](/contents/samsung/180916.md) +* [#issue1] 치킨 배달 +* [#issue2] 드래곤 커브 +* [#issue3] 사다리 조작 +* [#issue4] 감시 + +### 기출 문제 (2) +:heavy_check_mark: [issue 정리 내용](/contents/samsung/180923.md) +* [#issue1] 톱니바퀴 +* [#issue2] 경사로 +* [#issue3] 스타트와 링크 +* [#issue4] 연산자 끼워넣기 +* [#issue5] 로봇 청소기 +* [#issue6] 연구소 + +### 기출 문제 (3) +:heavy_check_mark: [issue 정리 내용](/contents/samsung/180930.md) +* [#issue1] 퇴사 +* [#issue2] 테트로미노 +* [#issue3] 주사위 굴리기 +* [#issue4] 시험 감독 +* [#issue5] 뱀 +* [#issue6] 구슬 탈출 2 + +### 기출 문제 (4) +:heavy_check_mark: [issue 정리 내용](/contents/samsung/181028.md) +* [#issue1] 큐빙 +* [#issue2] 인구 이동 +* [#issue3] 나무 재테크 +* [#issue4] 아기 상어 diff --git a/src/dami/Solution.java b/src/dami/Solution.java new file mode 100644 index 0000000..98f2eed --- /dev/null +++ b/src/dami/Solution.java @@ -0,0 +1,22 @@ +package dami; + +import dami.codility.Codility; +import dami.codinginterview.Interview; +import dami.codingtest.CodingTest; +import dami.hackerrank.HackerRank; +import dami.leetcode.Leetcode; +import dami.programmers.Programmers; +import dami.questions.Questions; + +public class Solution { + public static void main(String[] args) { + //new Codility().solutions(); + //new Leetcode().solutions(); + //new Programmers().solutions(); + //new HackerRank().solutions(); + //new Questions().solutions(); + + //new Interview().solutions(); + //new CodingTest().solutions(); + } +} diff --git a/src/dami/codility/Codility.java b/src/dami/codility/Codility.java new file mode 100644 index 0000000..16e0244 --- /dev/null +++ b/src/dami/codility/Codility.java @@ -0,0 +1,16 @@ +package dami.codility; + +import dami.codility.lesson5.review.GenomicRangeQuery; + +public class Codility { + public void solutions() { + //new BinaryGap().solution(328); + //new CyclicRotation().solution(new int[] {3, 8, 9, 7, 6}, 3); + //new OddOccurrencesInArray().solution(new int[] {9,3,9,3,9,7,9}); + //new MaxCounters().solution(5, new int[] {3,4,4,6,1,4,4}); + //new MissingInteger().solution(new int[] {1,3,6,4,1,2}); + //new CountDiv().solution(10, 10, 5); + //new CountDiv().solution(0, Integer.MAX_VALUE, 1); + new GenomicRangeQuery().solution("CAGCCTA", new int[] {2, 5, 0}, new int[] {4, 5, 6}); + } +} diff --git a/src/dami/codility/lesson1/BinaryGap.java b/src/dami/codility/lesson1/BinaryGap.java new file mode 100644 index 0000000..328e964 --- /dev/null +++ b/src/dami/codility/lesson1/BinaryGap.java @@ -0,0 +1,21 @@ +package dami.codility.lesson1; + +// 문제 : https://app.codility.com/programmers/lessons/1-iterations/binary_gap/ +// 결과 : https://app.codility.com/demo/results/trainingVA6BQ5-M7Z/ +public class BinaryGap { + public int solution(int N) { + String binaryString = Integer.toBinaryString(N); + int max = 0, count = 0; + + for (int i = 0; i < binaryString.length(); i++) { + if (binaryString.charAt(i) == '1') { + max = Math.max(max, count); + count = 0; + } else { + count++; + } + } + + return max; + } +} diff --git a/src/dami/codility/lesson2/CyclicRotation.java b/src/dami/codility/lesson2/CyclicRotation.java new file mode 100644 index 0000000..dcb9307 --- /dev/null +++ b/src/dami/codility/lesson2/CyclicRotation.java @@ -0,0 +1,31 @@ +package dami.codility.lesson2; + +import java.util.ArrayDeque; +import java.util.Deque; + +// 문제 : https://app.codility.com/programmers/lessons/2-arrays/cyclic_rotation/ +// 결과 : https://app.codility.com/demo/results/training6JDBK4-8SQ/ +public class CyclicRotation { + public int[] solution(int[] A, int K) { + if (null == A || A.length == 0) { + return A; + } + + Deque deque = new ArrayDeque<>(); + for (int num : A) { + deque.push(num); + } + + for (int i = 0; i < K % A.length; i++) { + deque.offer(deque.pop()); + } + + int i = 0; + while (!deque.isEmpty()) { + A[i] = deque.removeLast(); + i++; + } + + return A; + } +} diff --git a/src/dami/codility/lesson2/OddOccurrencesInArray.java b/src/dami/codility/lesson2/OddOccurrencesInArray.java new file mode 100644 index 0000000..1df46e1 --- /dev/null +++ b/src/dami/codility/lesson2/OddOccurrencesInArray.java @@ -0,0 +1,15 @@ +package dami.codility.lesson2; + +// 문제 : https://app.codility.com/programmers/lessons/2-arrays/odd_occurrences_in_array/ +// 결과 : https://app.codility.com/demo/results/trainingPGQRXT-CDK/ +public class OddOccurrencesInArray { + public int solution(int[] A) { + int result = 0; + for (int num : A) { + result ^= num; + } + + return result; + } + +} diff --git a/src/dami/codility/lesson3/FrogJmp.java b/src/dami/codility/lesson3/FrogJmp.java new file mode 100644 index 0000000..62805c0 --- /dev/null +++ b/src/dami/codility/lesson3/FrogJmp.java @@ -0,0 +1,10 @@ +package dami.codility.lesson3; + +// 문제 : https://app.codility.com/programmers/lessons/3-time_complexity/frog_jmp/ +// 결과 : https://app.codility.com/demo/results/trainingZW2P29-72A/ +public class FrogJmp { + public int solution(int X, int Y, int D) { + int total = Y - X; + return (total / D) + (total % D != 0 ? 1 : 0); + } +} diff --git a/src/dami/codility/lesson3/PermMissingElem.java b/src/dami/codility/lesson3/PermMissingElem.java new file mode 100644 index 0000000..7ad15bc --- /dev/null +++ b/src/dami/codility/lesson3/PermMissingElem.java @@ -0,0 +1,19 @@ +package dami.codility.lesson3; + +import java.util.Arrays; + +// 문제 : https://app.codility.com/programmers/lessons/3-time_complexity/perm_missing_elem/ +// 결과 : https://app.codility.com/demo/results/trainingMTKP8M-WJN/ +public class PermMissingElem { + public int solution(int[] A) { + Arrays.sort(A); + + for (int i = 0; i < A.length; i++) { + if (i + 1 != A[i]) { + return i + 1; + } + } + + return A.length + 1; + } +} diff --git a/src/dami/codility/lesson3/TapeEquilibrium.java b/src/dami/codility/lesson3/TapeEquilibrium.java new file mode 100644 index 0000000..1ad38f7 --- /dev/null +++ b/src/dami/codility/lesson3/TapeEquilibrium.java @@ -0,0 +1,23 @@ +package dami.codility.lesson3; + +// 문제 : https://app.codility.com/programmers/lessons/3-time_complexity/tape_equilibrium/ +// 결과 : https://app.codility.com/demo/results/trainingJPBA75-MDR/ +public class TapeEquilibrium { + public int solution(int[] A) { + int leftSum = A[0]; + int rightSum = 0; + for (int i = 1; i < A.length; i++) { + rightSum += A[i]; + } + + int min = Integer.MAX_VALUE; + for (int i = 1; i < A.length; i++) { + min = Math.min(min, Math.abs(leftSum - rightSum)); + + leftSum += A[i]; + rightSum -= A[i]; + } + + return min; + } +} diff --git a/src/dami/codility/lesson4/FrogRiverOne.java b/src/dami/codility/lesson4/FrogRiverOne.java new file mode 100644 index 0000000..3edb43e --- /dev/null +++ b/src/dami/codility/lesson4/FrogRiverOne.java @@ -0,0 +1,25 @@ +package dami.codility.lesson4; + +import java.util.HashSet; +import java.util.Set; + +// 문제 : https://app.codility.com/programmers/lessons/4-counting_elements/frog_river_one/ +// 결과 : https://app.codility.com/demo/results/trainingV9AWQG-H4S/ +public class FrogRiverOne { + public int solution(int X, int[] A) { + Set leaves = new HashSet<>(); + for (int i = 1; i <= X; i++) { + leaves.add(i); + } + + for (int i = 0; i < A.length; i++) { + leaves.remove(A[i]); + + if (leaves.isEmpty()) { + return i; + } + } + + return -1; + } +} diff --git a/src/dami/codility/lesson4/MissingInteger.java b/src/dami/codility/lesson4/MissingInteger.java new file mode 100644 index 0000000..eb5bef3 --- /dev/null +++ b/src/dami/codility/lesson4/MissingInteger.java @@ -0,0 +1,26 @@ +package dami.codility.lesson4; + +import java.util.Arrays; + +// ⭐️ +// 문제 : https://app.codility.com/programmers/lessons/4-counting_elements/missing_integer/ +// 결과 : https://app.codility.com/demo/results/trainingGWWV7R-UP7/ +public class MissingInteger { + public int solution(int[] A) { + Arrays.sort(A); + + int result = 1; + for (int num : A) { + if (num < result) { + continue; + } + + if (result < num) { + return result; + } + result++; + } + + return result; + } +} diff --git a/src/dami/codility/lesson4/PermCheck.java b/src/dami/codility/lesson4/PermCheck.java new file mode 100644 index 0000000..e926912 --- /dev/null +++ b/src/dami/codility/lesson4/PermCheck.java @@ -0,0 +1,24 @@ +package dami.codility.lesson4; + +import java.util.HashSet; +import java.util.Set; + +// 문제 : https://app.codility.com/programmers/lessons/4-counting_elements/perm_check/ +// 결과 : https://app.codility.com/demo/results/trainingH5WZAU-9AZ/ +public class PermCheck { + public int solution(int[] A) { + Set distinct = new HashSet<>(); + for (int num : A) { + if (num > A.length) { + return 0; + } + + if (distinct.contains(num)) { + return 0; + } + + distinct.add(num); + } + return 1; + } +} diff --git a/src/dami/codility/lesson4/review/MaxCounters.java b/src/dami/codility/lesson4/review/MaxCounters.java new file mode 100644 index 0000000..9487155 --- /dev/null +++ b/src/dami/codility/lesson4/review/MaxCounters.java @@ -0,0 +1,38 @@ +package dami.codility.lesson4.review; + +// ⭐️ +// 문제 : https://app.codility.com/programmers/lessons/4-counting_elements/max_counters/ +// 결과1 (타임아웃) : https://app.codility.com/demo/results/trainingN3KWEQ-8DS/ +// 결과2 : https://app.codility.com/demo/results/trainingEX47UA-2RY/ + +// position이 N+1일 때 매번 maxCounter 찍어주면 타임아웃 발생 +public class MaxCounters { + public int[] solution(int N, int[] A) { + int[] result = new int[N]; + int max = 0; + int finalMax = 0; + for (int position : A) { + if (position == N + 1) { + finalMax = max; + } else { + if (result[position - 1] < finalMax) { + result[position - 1] = finalMax; + } + max = Math.max(max, ++result[position - 1]); + } + } + + maxUp(result, finalMax); + + return result; + } + + private void maxUp(int[] result, int max) { + for (int i = 0; i < result.length; i++) { + if (result[i] < max) { + result[i] = max; + } + } + } + +} diff --git a/src/dami/codility/lesson5/CountDiv.java b/src/dami/codility/lesson5/CountDiv.java new file mode 100644 index 0000000..e99f231 --- /dev/null +++ b/src/dami/codility/lesson5/CountDiv.java @@ -0,0 +1,24 @@ +package dami.codility.lesson5; + +import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ; + +// 문제 : https://app.codility.com/programmers/lessons/5-prefix_sums/count_div/ +// 결과 : https://app.codility.com/demo/results/trainingN8CPTP-SQY/ +public class CountDiv { + // 시간 : O(1) + public int solution(int A, int B, int K) { + return (B / K) - (A % K == 0 ? A / K - 1 : A / K); + } + + // 시간 : O(B-A) => O(1) 방법 있을듯 + public int timeout(int A, int B, int K) { + int result = 0; + for (int i = A; i <= B; i++) { + if (i % K == 0) { + result++; + } + } + + return result; + } +} diff --git a/src/dami/codility/lesson5/review/GenomicRangeQuery.java b/src/dami/codility/lesson5/review/GenomicRangeQuery.java new file mode 100644 index 0000000..1eb9ae6 --- /dev/null +++ b/src/dami/codility/lesson5/review/GenomicRangeQuery.java @@ -0,0 +1,46 @@ +package dami.codility.lesson5.review; + +import java.util.*; + +// ⭐️ Prefix Sum 알고리즘 +// 문제 : https://app.codility.com/programmers/lessons/5-prefix_sums/genomic_range_query/ +// 결과 : 62% +public class GenomicRangeQuery { + + // 시간 : O(n) + public int[] solution(String S, int[] P, int[] Q) { + Map dnaMap = new HashMap<>(); + dnaMap.put('A', 1); + dnaMap.put('C', 2); + dnaMap.put('G', 3); + dnaMap.put('T', 4); + + int[][] prefix = new int[S.length()][dnaMap.size()]; + for (int i = 0; i < S.length(); i++) { + prefix[i][dnaMap.get(S.charAt(i)) - 1]++; + } + + return null; + } + + // 시간 : O(n^2) => O(n) 방법 찾기 + public int[] timeout(String S, int[] P, int[] Q) { + Map dnaMap = new HashMap<>(); + dnaMap.put('A', 1); + dnaMap.put('C', 2); + dnaMap.put('G', 3); + dnaMap.put('T', 4); + + int[] result = new int[P.length]; + for (int i = 0; i < P.length; i++) { + int min = Integer.MAX_VALUE; + for (int j = P[i]; j <= Q[i]; j++) { + min = Math.min(min, dnaMap.get(S.charAt(j))); + if (min == 1) break; + } + result[i] = min; + } + + return result; + } +} diff --git a/src/dami/codinginterview/Interview.java b/src/dami/codinginterview/Interview.java new file mode 100644 index 0000000..e1222fb --- /dev/null +++ b/src/dami/codinginterview/Interview.java @@ -0,0 +1,68 @@ +package dami.codinginterview; + +import dami.codinginterview.common.ListNode; +import dami.codinginterview.common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + +public class Interview { + public void solutions() { + //new Array3().twoSum(new int[] {2, 3, 4, 7, 8, 9}, 12); + //new Array4().sorting(new int[]{10, 5, 8, 7, 3, 9}); + + //new List1().reverseList(new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(6, new ListNode(7)))))); + //new List2().findNthNodeFromEnd(2, new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(6, new ListNode(7)))))); + //new List3().distinct(new ListNode(2, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(4, new ListNode(4))))))); + //new List4().circleOrNot(circleNode()); + + //new Stack1().reverse(stack()); + //new Stack2().isPair("[{1+2*(2+2)}-[1-3)]"); + //new Stack2().isPair("())))"); + //new Stack3().calculatePostfix("123+-5*"); + //new Stack4().span(new int[] {5,3,2,6,7,1,4}); + + //new Queue1().reverseQueue(queue()); + //new Queue2().lruCache(); + //new Queue3().levelSum(treeNode()); + //new Queue4().implementStackByQueue(); + + //new Tree1().findNthNode(treeNode(), 5); + //new Tree1_1().findTreeDepth(treeNode()); + //new Tree2().makeBinaryTree(new int[] {4,2,5,1,3}, new int[] {1,2,4,5,3}); + //new Tree2().makeBinaryTree_최적화(new int[] {4,2,5,1,3}, new int[] {1,2,4,5,3}); + } + + private ListNode circleNode() { + ListNode three = new ListNode(3); + ListNode node = new ListNode(1, new ListNode(2)); + node.add(three); + node.add(new ListNode(4, new ListNode(5))); + node.add(three); + return node; + } + + private Stack stack() { + Stack stack = new Stack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + return stack; + } + + private Queue queue() { + Queue queue = new LinkedList<>(); + queue.offer(1); + queue.offer(2); + queue.offer(3); + queue.offer(4); + queue.offer(5); + return queue; + } + + private TreeNode treeNode() { + TreeNode tree = new TreeNode(9, new TreeNode(2, new TreeNode(1), new TreeNode(5)), new TreeNode(3, null, new TreeNode(4))); + return tree; + } +} diff --git a/src/dami/codinginterview/array/Array3.java b/src/dami/codinginterview/array/Array3.java new file mode 100644 index 0000000..6488300 --- /dev/null +++ b/src/dami/codinginterview/array/Array3.java @@ -0,0 +1,59 @@ +package dami.codinginterview.array; + +import java.util.HashMap; +import java.util.Map; + +public class Array3 { + public int[] twoSum(int[] numbers, int target) { + //return iteration(numbers, target); + //return useHashMap(numbers, target); + return threeSum(numbers, target); + } + + // 시간 : O(n^2), 공간 : O(1) + private int[] iteration(int[] numbers, int target) { + for (int i = 0; i < numbers.length; i++) { + for (int j = i + 1; j < numbers.length; j++) { + if (numbers[i] + numbers[j] == target) { + return new int[] {i, j}; + } + } + } + + return null; + } + + // 시간 : O(n), 공간 : O(n) + private int[] useHashMap(int[] numbers, int target) { + Map indexMap = new HashMap<>(); + for (int i = 0; i < numbers.length; i++) { + int otherValue = Math.abs(target - numbers[i]); + if (indexMap.containsKey(otherValue)) { + return new int[] {i, indexMap.get(otherValue)}; + } + indexMap.put(numbers[i], i); + } + + return null; + } + + // 시간 : O(n^2), 공간 : O(n) + private int[] threeSum(int[] numbers, int target) { + Map indexMap = new HashMap<>(); + for (int i = 0; i < numbers.length; i++) { + indexMap.put(numbers[i], i); + } + + for (int i = 0; i < numbers.length; i++) { + int newTarget = target - numbers[i]; + for (int j = i + 1; j < numbers.length; j++) { + int otherValue = newTarget - numbers[j]; + if (indexMap.containsKey(otherValue) && indexMap.get(otherValue) != j) { + return new int[] {i, j, indexMap.get(otherValue)}; + } + } + } + + return null; + } +} diff --git a/src/dami/codinginterview/array/Array4.java b/src/dami/codinginterview/array/Array4.java new file mode 100644 index 0000000..50966ea --- /dev/null +++ b/src/dami/codinginterview/array/Array4.java @@ -0,0 +1,43 @@ +package dami.codinginterview.array; + +public class Array4 { + public int[] sorting(int[] array) { + return mySolution(array); + //return solution(array); + } + + private int[] mySolution(int[] array) { + int[] sorted = new int[array.length * 2]; + + for (int number : array) { + sorted[number - 1] = number; + } + + int index = 0; + for (int number : sorted) { + if (number != 0) { + array[index++] = number; + } + } + + return array; + } + + private int[] solution(int[] array) { + boolean[] booleans = new boolean[array.length * 2]; + + for (int number : array) { + booleans[number] = true; + } + + int[] sorted = new int[array.length]; + int index = 0; + for (int i = 0; i < booleans.length; i++) { + if (booleans[i]) { + sorted[index++] = i; + } + } + + return sorted; + } +} diff --git a/src/dami/codinginterview/common/ListNode.java b/src/dami/codinginterview/common/ListNode.java new file mode 100644 index 0000000..1433881 --- /dev/null +++ b/src/dami/codinginterview/common/ListNode.java @@ -0,0 +1,25 @@ +package dami.codinginterview.common; + +public class ListNode { + public int val; + public ListNode next; + + public ListNode() { } + + public ListNode(int val) { + this.val = val; + } + + public ListNode(int val, ListNode next) { + this.val = val; + this.next = next; + } + + public void add(ListNode node) { + ListNode current = this; + while (current.next != null) { + current = current.next; + } + current.next = node; + } +} diff --git a/src/dami/codinginterview/common/TreeNode.java b/src/dami/codinginterview/common/TreeNode.java new file mode 100644 index 0000000..0e888ad --- /dev/null +++ b/src/dami/codinginterview/common/TreeNode.java @@ -0,0 +1,15 @@ +package dami.codinginterview.common; + +public class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + public TreeNode() {} + public TreeNode(int val) { this.val = val; } + public TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } + +} diff --git a/src/dami/codinginterview/list/List1.java b/src/dami/codinginterview/list/List1.java new file mode 100644 index 0000000..c74863b --- /dev/null +++ b/src/dami/codinginterview/list/List1.java @@ -0,0 +1,56 @@ +package dami.codinginterview.list; + +import dami.codinginterview.common.ListNode; + +public class List1 { + // 1 2 3 6 7 + public ListNode reverseList(ListNode node) { + //return mySolutionByIterative(node); + //return solutionByRecursive(node); + //return solutionByIterative(node); + return solutionByRecursive(node); + } + + // 새로 생성하는 노드(reversed)에게 이전 노드 리스트(current) 이어 붙이기 + private ListNode mySolutionByIterative(ListNode node) { + ListNode reversed = null; + ListNode current = null; + while (null != node) { + reversed = new ListNode(node.val); + reversed.next = current; + current = reversed; + node = node.next; + } + + return reversed; + } + + + private ListNode solutionByIterative(ListNode node) { + ListNode current = node; + ListNode prev = null; + ListNode next = null; + + while (current != null) { + next = current.next; + current.next = prev; + prev = current; + current = next; + } + + return prev; + } + + private ListNode solutionByRecursive(ListNode node) { + if (node == null || node.next == null) { + return node; + } + + ListNode reversedNode = solutionByRecursive(node.next); + node.next.next = node; + node.next = null; + + return reversedNode; + } + +} diff --git a/src/dami/codinginterview/list/List2.java b/src/dami/codinginterview/list/List2.java new file mode 100644 index 0000000..a8325ea --- /dev/null +++ b/src/dami/codinginterview/list/List2.java @@ -0,0 +1,98 @@ +package dami.codinginterview.list; + +import dami.codinginterview.common.ListNode; + +import java.util.HashMap; +import java.util.Map; + +public class List2 { + public ListNode findNthNodeFromEnd(int n, ListNode node) { + //return mySolution(n, node); + //return solution1(n, node); + //return solution2(n, node); + return solution3(n, node); + } + + // 시간 : O(n) + // 공간 : O(1) + private ListNode mySolution(int n, ListNode node) { + if (null == node) { + return null; + } + + int nodeSize = sizeOf(node); + for (int i = 0; i < nodeSize - n; i++) { + node = node.next; + } + return node; + } + + private int sizeOf(ListNode node) { + ListNode head = node; + int size = 0; + + while (null != head) { + size++; + head = head.next; + } + + return size; + } + + // using Map + // 시간 : O(n) + // 공간 : O(n) + private ListNode solution1(int n, ListNode node) { + Map nodeMap = new HashMap<>(); + int key = 0; + while (null != node) { + nodeMap.put(key++, node); + node = node.next; + } + + return nodeMap.get(nodeMap.size() - n); + } + + // mySolution과 동일한 해결 방법 + // 시간 : O(n) 단, 순회를 두 번 + // 공간 : O(1) + private ListNode solution2(int n, ListNode node) { + ListNode current = node; + int length = 0; + while (current != null) { + length++; + current = current.next; + } + + ListNode target = node; + int targetIndex = length - n; + while (targetIndex > 0) { + targetIndex--; + target = target.next; + } + + return target; + } + + // left, right 두 개의 포인터를 사용하여 한 번만 순회하는 방법 + // left와 right 사이 간격을 n - 1만큼 주고 right이 끝 노드에 도달했을 때 left가 가리키는 노드를 반환 + // 시간 : O(n) 순회 한 번 + // 공간 : O(1) + private ListNode solution3(int n, ListNode node) { + ListNode left = node; + ListNode right = node; + + int between = 0; + while (right.next != null) { + right = right.next; + + if (between < n - 1) { + between++; + } else { + left = left.next; + } + } + + return left; + } +} diff --git a/src/dami/codinginterview/list/List3.java b/src/dami/codinginterview/list/List3.java new file mode 100644 index 0000000..ad6cf8f --- /dev/null +++ b/src/dami/codinginterview/list/List3.java @@ -0,0 +1,129 @@ +package dami.codinginterview.list; + +import dami.codinginterview.common.ListNode; + +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +public class List3 { + public ListNode distinct(ListNode node) { + //return mySolution(node); + //return solution1(node); + //return solution2(node); + return solution3(node); + //return solution4(node); + } + + // 시간 : O(n) 단, 순회 두 번 + // 공간 : O(n) + private ListNode mySolution(ListNode node) { + Set set = new LinkedHashSet<>(); + while (null != node) { + set.add(node.val); + node = node.next; + } + + ListNode head = null; + ListNode current = null; + for (Integer number : set) { + ListNode newNode = new ListNode(number); + + if (null == current) { + current = newNode; + head = current; + } else { + current.next = newNode; + current = current.next; + } + } + + return head; + } + + // 시간 : O(n) + // 공간 : O(1) + private ListNode solution1(ListNode node) { + ListNode current = node; + + while (current != null) { + ListNode temp = current; + while (temp != null && current.val == temp.val) { + temp = temp.next; + } + + current.next = temp; + current = current.next; + } + + return node; + } + + // prev와 current를 두고 한 노드 씩 이동 하면서 값 비교 + // 만약 prev 노드 값과 current 노드 값이 같다면 current만 다음 노드로 이동 + // 두 노드 값이 달라졌을 때 prev의 next를 current로 변경 + // 시간 : O(n) + // 공간 : O(1) + private ListNode solution2(ListNode node) { + ListNode current = node; + ListNode prev = node; + + while (current != null) { + if(prev.val != current.val) { + prev.next = current; + prev = current; + } + current = current.next; + + if (current == null) { + prev.next = null; + } + } + return node; + } + + // recursive + // 시간 : O(n) + // 공간 : O(n) + private ListNode solution3(ListNode node) { + recursive(node); + return node; + } + + private void recursive(ListNode node) { + if (node == null) { + return; + } + + if (node.next != null) { + if (node.val == node.next.val) { + node.next = node.next.next; + recursive(node); + } else { + recursive(node.next); + } + } + } + + // using Set + // mySolution에서 순회 1번으로 축소 + // 시간 : O(n) + // 공간 : O(n) + private ListNode solution4(ListNode node) { + Set set = new HashSet<>(); + ListNode current = node; + ListNode prev = null; + + while (current != null) { + if (set.contains(current.val)) { // 중복 + prev.next = current.next; + } else { + set.add(current.val); + prev = current; + } + + current = current.next; + } + return node; + } +} diff --git a/src/dami/codinginterview/list/List4.java b/src/dami/codinginterview/list/List4.java new file mode 100644 index 0000000..57e78dd --- /dev/null +++ b/src/dami/codinginterview/list/List4.java @@ -0,0 +1,65 @@ +package dami.codinginterview.list; + +import dami.codinginterview.common.ListNode; + +import java.util.HashSet; +import java.util.Set; + +public class List4 { + public boolean circleOrNot(ListNode node) { + //return mySolution(node); + return solution3(node); + } + + // 시간 : O(n) + // 공간 : O(1) ~ O(n) + private boolean mySolution(ListNode node) { + ListNode current = node; + + Set nodeSet = new HashSet<>(); + while (current != null) { + if (nodeSet.contains(current)) { + return true; + } + nodeSet.add(current); + current = current.next; + } + + return false; + } + + // 가장 단순한 방법 + // 하지만 솔루션이 될 수 없음 + private boolean solution1(ListNode node) { + // 노드를 순회하면서 현재 노드가 다음 노드 중에 중복으로 나타나는지 확인하는 방법 + // 1 -> 2 -> 3 -> 4 -> 3 이라면 3과 4에서 무한루프에 빠질 수 있기 때문 + return false; + } + + // mySolution과 동일한 방법 (node로 비교) + private boolean solution2(ListNode node) { + return false; + } + + // 시간 : O(n) + // 공간 : O(1) + // 플로이드 알고리즘? + // 원 위를 순환하는 두 점의 속도가 다를 때 두 점은 언젠가는 반드시 만나게 되어있는 특징을 이용 + private boolean solution3(ListNode node) { + ListNode slow = node; + ListNode fast = node; + while (slow != null && fast != null) { + if (fast.next == null || fast.next.next == null) { + return false; + } + + fast = fast.next.next; + if (slow.equals(fast)) { + return true; + } + slow = slow.next; + } + + return false; + } +} diff --git a/src/dami/codinginterview/queue/Queue1.java b/src/dami/codinginterview/queue/Queue1.java new file mode 100644 index 0000000..3b32911 --- /dev/null +++ b/src/dami/codinginterview/queue/Queue1.java @@ -0,0 +1,78 @@ +package dami.codinginterview.queue; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + +// queue의 연산 offer(), poll(), isEmpty()만 사용 가능 +public class Queue1 { + public Queue reverseQueue(Queue queue) { + //return mySolutionByIterating(queue); + return mySolutionByRecursive(queue); + } + + // 시간 : O(n^2) + // 공간 : O(n)? O(n^2)? + // 비효율적인듯.. => 큐만 써야 하는 줄 알았는데 강의 보니 스택 써서 간단하게 해결했다. ^_ㅠ + private Queue mySolutionByIterating(Queue queue) { + Queue reversedQueue = new LinkedList<>(); + Queue tempQueue = new LinkedList<>(); + + while (!queue.isEmpty()) { + int current = queue.poll(); + if (reversedQueue.isEmpty()) { + reversedQueue.offer(current); + } else { + while (!reversedQueue.isEmpty()) { + tempQueue.offer(reversedQueue.poll()); + } + reversedQueue.offer(current); + while (!tempQueue.isEmpty()) { + reversedQueue.offer(tempQueue.poll()); + } + } + } + + return reversedQueue; + } + + // 시간 : O(n) + // 공간 : O(n) + private Queue mySolutionByRecursive(Queue queue) { + recursive(queue); + return queue; + } + + private void recursive(Queue queue) { + if (queue.isEmpty()) { + return; + } + + int temp = queue.poll(); + recursive(queue); + queue.offer(temp); + } + + private Queue solution1(Queue queue) { + Stack stack = new Stack<>(); + while (!queue.isEmpty()) { + stack.push(queue.poll()); + } + while (!stack.isEmpty()) { + queue.offer(stack.pop()); + } + return queue; + } + + private Queue solution2(Queue queue) { + if (queue.isEmpty()) { + return queue; + } + + int front = queue.poll(); + queue = solution2(queue); + queue.offer(front); + + return queue; + } +} diff --git a/src/dami/codinginterview/queue/Queue2.java b/src/dami/codinginterview/queue/Queue2.java new file mode 100644 index 0000000..b79731c --- /dev/null +++ b/src/dami/codinginterview/queue/Queue2.java @@ -0,0 +1,188 @@ +package dami.codinginterview.queue; + +import dami.Solution; + +import java.util.*; + +public class Queue2 { + public void lruCache() { + //MyLRUCache cache = new MyLRUCache(3); + //LRUCache cache = LRUCache.newInstance(3); + Solution2 cache = new Solution2(3); + cache.query(3); + cache.print(); + + cache.query(5); + cache.print(); + cache.query(1); + cache.print(); + cache.query(2); + cache.print(); + cache.query(3); + cache.print(); + cache.query(4); + cache.print(); + cache.query(3); + cache.print(); + cache.query(2); + cache.print(); + cache.query(5); + cache.print(); + + } +} + +// 가장 기본적인 방법 +class MyLRUCache { + private final int cacheSize; + private final Queue cache; + + public MyLRUCache(int cacheSize) { + this.cacheSize = cacheSize; + this.cache = new LinkedList<>(); + } + + // 시간 : O(n). LinkedList의 remove는 해당 원소를 찾아서 삭제하기 때문에 한 번 순회 필요 + public void query(int number) { + cache.remove(number); + + if (cache.size() == cacheSize) { + cache.poll(); + } + cache.offer(number); + } + + public void print() { + System.out.println(cache); + } +} + +// LinkedHashMap의 removeEldestEntry 메소드 활용 +class LRUCache extends LinkedHashMap { + private final int cacheSize; + + private LRUCache(int cacheSize) { + super(cacheSize, 0.75f, true); + this.cacheSize = cacheSize; + } + + public static LRUCache newInstance(int cacheSize) { + return new LRUCache<>(cacheSize); + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return cacheSize < this.size(); + } + + public void query(K number) { + put(number, (V) number); + } + + public void print() { + System.out.println(keySet()); + } +} + +// 솔루션1. 더블링크드리스트와 Map 활용 +class Solution1 { + private final int cacheSize; + private final Map map; + private DoubleNode head, tail; + + public Solution1(int cacheSize) { + this.cacheSize = cacheSize; + this.map = new HashMap<>(); + } + + class DoubleNode { + int value; + DoubleNode prev; + DoubleNode next; + + public DoubleNode(int value) { + this.value = value; + } + } + + public void query(int number) { + if (map.containsKey(number)) { + DoubleNode node = map.get(number); + remove(node); + addToHead(node); + } else { + DoubleNode newNode = new DoubleNode(number); + if (map.size() == cacheSize) { + map.remove(tail.value); + remove(tail); + } + addToHead(newNode); + map.put(number, newNode); + } + } + + public void addToHead(DoubleNode node) { + node.next = head; + node.prev = null; + + if (head != null) { + head.prev = node; + } + + head = node; + + if (tail == null) { + tail = head; + } + } + + public void remove(DoubleNode node) { + if (node.prev != null) { + node.prev.next = node.next; + } else { + head = node.next; + } + + if (node.next != null) { + node.next.prev = node.prev; + } else { + tail = node.prev; + } + } + + public void print() { + DoubleNode current = this.head; + while (current != null) { + System.out.print(current.value + " "); + current = current.next; + } + System.out.println(); + } + +} + +// 솔루션2. LinkedHashSet 사용 +class Solution2 { + private final int cacheSize; + private final Set cache; + + public Solution2(int cacheSize) { + this.cacheSize = cacheSize; + this.cache = new LinkedHashSet<>(); + } + + public void query(int number) { + cache.remove(number); // number 있으면 삭제 없으면 아무것도 안함 + + if (cacheSize == cache.size()) { + int first = cache.iterator().next(); + cache.remove(first); + } + + cache.add(number); + } + + public void print() { + System.out.println(cache); + } +} diff --git a/src/dami/codinginterview/queue/Queue3.java b/src/dami/codinginterview/queue/Queue3.java new file mode 100644 index 0000000..42774e4 --- /dev/null +++ b/src/dami/codinginterview/queue/Queue3.java @@ -0,0 +1,72 @@ +package dami.codinginterview.queue; + +import dami.codinginterview.common.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +public class Queue3 { + // 시간 : O(n) + // 공간 : O(B), B는 트리 한 계층의 최대 너비. 생성하는 큐에는 트리 한 계층의 노드만 들어가기 때문 + public int levelSum(TreeNode root) { + if (root == null) { + return 0; + } + + Queue nodes = new LinkedList<>(); + + nodes.offer(root); + + int max = root.val; + int sum = 0; + int levelSize = nodes.size(); + while (!nodes.isEmpty()) { + TreeNode node = nodes.poll(); + levelSize--; + + sum += node.val; + + if (node.left != null) nodes.offer(node.left); + if (node.right != null) nodes.offer(node.right); + + if (levelSize == 0) { + max = Math.max(sum, max); + sum = 0; + levelSize = nodes.size(); + } + } + + return max; + } + + // 시간 : O(n) + // 공간 : O(B) + public int solution(TreeNode root) { + if (root == null) { + return 0; + } + + int result = root.val; + + Queue queue = new LinkedList<>(); + queue.offer(root); + + while (!queue.isEmpty()) { + int count = queue.size(); + int sum = 0; + + while (count > 0) { + count--; + TreeNode node = queue.poll(); + sum += node.val; + + if (node.left != null) queue.offer(node.left); + if (node.right != null) queue.offer(node.right); + } + + result = Math.max(result, sum); + } + + return result; + } +} diff --git a/src/dami/codinginterview/queue/Queue4.java b/src/dami/codinginterview/queue/Queue4.java new file mode 100644 index 0000000..578108b --- /dev/null +++ b/src/dami/codinginterview/queue/Queue4.java @@ -0,0 +1,115 @@ +package dami.codinginterview.queue; + +import java.util.LinkedList; +import java.util.Queue; + +// 두 가지 방법으로 풀이 가능 +// 1. 넣을 때 O(n), 꺼낼 때 O(1)인 방법 +// 2. 넣을 때 O(1), 꺼낼 때 O(n)인 방법 +// 둘 중 어떤 방법으로 풀 지 물어보기 +public class Queue4 { + public void implementStackByQueue() { + MyQueueStack stack = new MyQueueStack(); + stack.push(3); + stack.push(4); + stack.push(10); + stack.push(5); + + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + } +} + +// 넣을 때 O(n), 꺼낼 때 O(1)인 방법 사용 +class MyQueueStack { + private final Queue queue; + + public MyQueueStack() { + this.queue = new LinkedList<>(); + } + + public void push(int value) { + if (queue.isEmpty()) { + queue.offer(value); + return; + } + + Queue temp = new LinkedList<>(); + + while (!queue.isEmpty()) { + temp.offer(queue.poll()); + } + + queue.offer(value); + + // 반복을 한 번 더 하는 대신 한쪽으로 몰아놓고 queue와 temp를 치환하여 사용하는 방법도 가능 (솔루션 참고) + while (!temp.isEmpty()) { + queue.offer(temp.poll()); + } + } + + public int pop() { + if (queue.isEmpty()) { + throw new IllegalArgumentException(); + } + return queue.poll(); + } +} + +// 솔루션 1 +// 넣을 때 O(n), 꺼낼 때 O(1)인 방법 +class QueueStack1 { + Queue main = new LinkedList<>(); + Queue sub = new LinkedList<>(); + + public void push(int value) { + sub.offer(value); + while (!main.isEmpty()) { + sub.offer(main.poll()); + } + + Queue temp = main; + main = sub; + sub = temp; + } + + public int pop() { + if (main.isEmpty()) { + throw new IllegalArgumentException(); + } + + return main.poll(); + } +} + +// 솔루션 2 +// 넣을 때 O(1), 꺼낼 때 O(n)인 방법 +class QueueStack2 { + Queue main = new LinkedList<>(); + Queue sub = new LinkedList<>(); + + public void push(int value) { + main.offer(value); + } + + public int pop() { + if (main.isEmpty()) { + throw new IllegalArgumentException(); + } + + // 마지막 한 개만 빼고 옮기기 + while (main.size() > 1) { + sub.offer(main.poll()); + } + + int result = main.poll(); + + Queue temp = main; + main = sub; + sub = temp; + + return result; + } +} diff --git a/src/dami/codinginterview/stack/Stack1.java b/src/dami/codinginterview/stack/Stack1.java new file mode 100644 index 0000000..099d812 --- /dev/null +++ b/src/dami/codinginterview/stack/Stack1.java @@ -0,0 +1,61 @@ +package dami.codinginterview.stack; + +import java.util.Stack; + +public class Stack1 { + public Stack reverse(Stack stack) { + //return mySolution1(stack); + solution(stack); + return stack; + } + + // 시간 : O(n) + // 공간 : O(1) + private Stack mySolution1(Stack stack) { + int size = stack.size(); + for (int i = 0; i < size / 2; i++) { + swap(stack, i, size - i - 1); + } + return stack; + } + + private void swap(Stack stack, int i, int j) { + int temp = stack.elementAt(i); + stack.setElementAt(stack.elementAt(j), i); + stack.setElementAt(temp, j); + } + + // 시간 : O(n) + // 공간 : O(n) + private Stack mySolution2(Stack stack) { + Stack reversed = new Stack<>(); + while (!stack.isEmpty()) { + reversed.push(stack.pop()); + } + return reversed; + } + + // 다른 자료구조를 사용하지 않고 재귀적으로 Stack만 사용 + // 시간 : O(n^2) + // 공간 : O(n), 메모리를 계속 잡고 있지 않기 때문에 n + private void solution(Stack stack) { + if (stack.isEmpty()) { + return; + } + + int value = stack.pop(); + solution(stack); + insertAtBottom(stack, value); + } + + private void insertAtBottom(Stack stack, int number) { + if (stack.isEmpty()) { + stack.push(number); + return; + } + + int value = stack.pop(); + insertAtBottom(stack, number); + stack.push(value); + } +} diff --git a/src/dami/codinginterview/stack/Stack2.java b/src/dami/codinginterview/stack/Stack2.java new file mode 100644 index 0000000..600b5ef --- /dev/null +++ b/src/dami/codinginterview/stack/Stack2.java @@ -0,0 +1,56 @@ +package dami.codinginterview.stack; + +import java.util.*; + +// 스택 혹은 디큐를 써도 되는지 묻기 +public class Stack2 { + public boolean isPair(String expression) { + return mySolution(expression); + } + + private boolean mySolution(String expression) { + Map brackets = new HashMap<>(); + brackets.put('[', ']'); + brackets.put('{', '}'); + brackets.put('(', ')'); + + Stack stack = new Stack<>(); + for (int i = 0; i < expression.length(); i++) { + char current = expression.charAt(i); + if (brackets.containsKey(current)) { + stack.push(current); + // TODO "(())))" 같은 경우 고려 필요 + } else if (!stack.isEmpty() && brackets.get(stack.peek()) == current) { + stack.pop(); + } + } + + return stack.isEmpty(); + } + + // 시간 : O(n) + // 공간 : O(n) + private boolean solution(String expression) { + List openingBrackets = Arrays.asList('[', '{', '('); + List closingBrackets = Arrays.asList(']', '}', ')'); + + Stack brackets = new Stack<>(); + for (int i = 0; i < expression.length(); i++) { + char current = expression.charAt(i); + if (openingBrackets.contains(current)) { + brackets.push(current); + } else if (closingBrackets.contains(current)) { + if (brackets.isEmpty()) { + return false; + } + + Character bracket = brackets.pop(); + if (openingBrackets.indexOf(bracket) != closingBrackets.indexOf(current)) { + return false; + } + } + } + + return brackets.isEmpty(); + } +} diff --git a/src/dami/codinginterview/stack/Stack3.java b/src/dami/codinginterview/stack/Stack3.java new file mode 100644 index 0000000..77b524c --- /dev/null +++ b/src/dami/codinginterview/stack/Stack3.java @@ -0,0 +1,108 @@ +package dami.codinginterview.stack; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Set; +import java.util.Stack; + +public class Stack3 { + public int calculatePostfix(String postfix) { + return mySolution(postfix); + } + + private int mySolution(String postfix) { + Set operators = new HashSet<>(); + operators.add('+'); + operators.add('-'); + operators.add('*'); + operators.add('/'); + + Stack stack = new Stack<>(); + for (int i = 0; i < postfix.length(); i++) { + char current = postfix.charAt(i); + if (!operators.contains(current)) { + stack.push(current - '0'); + } else { + int num2 = stack.pop(); + int num1 = stack.pop(); + stack.push(operate(num1, num2, current)); + } + } + + return stack.pop(); + } + + private int operate(int num1, int num2, int operator) { + switch (operator) { + case '+' : return num1 + num2; + case '-' : return num1 - num2; + case '*' : return num1 * num2; + case '/' : return num1 / num2; + } + throw new IllegalArgumentException("수식 오류"); + } + + private int solution(String postfix) { + LinkedList numbers = new LinkedList<>(); + char[] chars = postfix.trim().toCharArray(); + for (char c : chars) { + if (Character.isDigit(c)) { + numbers.push(c - '0'); + } else { + int right = numbers.pop(); + int left = numbers.pop(); + + switch (c) { + case '+' : numbers.push(left + right); break; + case '-' : numbers.push(left - right); break; + case '*' : numbers.push(left * right); break; + case '/' : numbers.push(left / right); break; + } + } + } + + return numbers.pop(); + } + + private String infixToPostfix(String infix) { + Stack operators = new Stack<>(); + + infix = infix.trim(); + StringBuilder postfix = new StringBuilder(); + + for (int i = 0; i < infix.length(); i++) { + char c = infix.charAt(i); + if (Character.isDigit(c)) { + postfix.append(c); + } else if (c == '(') { + operators.push(c); + } else if (c == ')') { + while (!operators.isEmpty() && operators.peek() != '(') { + postfix.append(operators.pop()); + } + operators.pop(); + } else { + while (!operators.isEmpty() && precedence(c) <= precedence(operators.peek())) { + postfix.append(operators.pop()); + } + + operators.push(c); + } + } + + while (!operators.isEmpty()) { + postfix.append(operators.pop()); + } + + return postfix.toString(); + } + + private int precedence(char c) { + if (c == '+' || c == '-') { + return 1; + } else if (c == '*' || c == '/') { + return 2; + } + return 0; + } +} diff --git a/src/dami/codinginterview/stack/Stack4.java b/src/dami/codinginterview/stack/Stack4.java new file mode 100644 index 0000000..58e3f21 --- /dev/null +++ b/src/dami/codinginterview/stack/Stack4.java @@ -0,0 +1,61 @@ +package dami.codinginterview.stack; + +import java.util.Stack; + +public class Stack4 { + public int[] span(int[] prices) { + return mySolution1(prices); + } + + // 현재까지 중 최고값 인덱스 기록 + // 전날보다 상승했으면 최고점부터 연속 구간 길이 계산 + // 전날보다 하락했으면 1 + private int[] mySolution1(int[] prices) { + int[] result = new int[prices.length]; + result[0] = 1; + + int maxIndex = 0; + for (int i = 1; i < prices.length; i++) { + if (prices[i] > prices[maxIndex]) { + maxIndex = i; + } + + if (prices[i] >= prices[i - 1]) { + if (maxIndex != i) { + result[i] = i - maxIndex; + } else { + result[i] = i + 1; + } + } else { + result[i] = 1; + } + } + + return result; + } + + // 5 3 2 4 7 1 + // index : 0 1 2 3 4 5 + // span : 1 + // 스택에 index를 넣는 것 + // 현재 값 > 스택 peek한 index의 값이면 span 값 계산 후 현재 값 push + // 아니면 index의 값일 클 때까지 pop하고 span 값 계산 후 현재 값 push + // span 값은 현재 인덱스 - 스택 peek 인덱스 + private int[] solution(int[] prices) { + int[] result = new int[prices.length]; + Stack indexes = new Stack<>(); + indexes.push(0); + result[0] = 1; + + for (int i = 1; i < prices.length; i++) { + while (!indexes.isEmpty() && prices[i] >= prices[indexes.peek()]) { + indexes.pop(); + } + + result[i] = indexes.isEmpty() ? i + 1 : i - indexes.peek(); + indexes.push(i); + } + + return result; + } +} diff --git a/src/dami/codinginterview/tree/Tree.java b/src/dami/codinginterview/tree/Tree.java new file mode 100644 index 0000000..b2421e7 --- /dev/null +++ b/src/dami/codinginterview/tree/Tree.java @@ -0,0 +1,41 @@ +package dami.codinginterview.tree; + + +import com.sun.corba.se.impl.orbutil.StackImpl; +import dami.codinginterview.common.TreeNode; + +import java.util.Stack; + +public class Tree { + public void inorderIterating(TreeNode node) { + if (node == null) { + return; + } + + Stack stack = new Stack<>(); + while (true) { + while (node != null) { + stack.push(node); + node = node.left; + } + + if (stack.isEmpty()) { + break; + } + + node = stack.pop(); + System.out.println(node.val); + node = node.right; + } + } + + public void inorderRecursive(TreeNode node) { + if (node == null) { + return; + } + + inorderRecursive(node.left); + System.out.println(node.val); + inorderRecursive(node.right); + } +} diff --git a/src/dami/codinginterview/tree/Tree1.java b/src/dami/codinginterview/tree/Tree1.java new file mode 100644 index 0000000..7c6801a --- /dev/null +++ b/src/dami/codinginterview/tree/Tree1.java @@ -0,0 +1,44 @@ +package dami.codinginterview.tree; + +import dami.codinginterview.common.TreeNode; + +public class Tree1 { + public void findNthNode(TreeNode root, int n) { + mySolution(root, n - 1); + solution(root, n - 1); + } + + private int mySolution(TreeNode node, int n) { + if (node == null) { + return n + 1; + } + + if (n < 0) { + return n; + } + + if (n == 0) { + System.out.println(node.val); + } + + n = mySolution(node.left, --n); + n = mySolution(node.right, --n); + + return n; + } + + private int count = 0; + private void solution(TreeNode node, int n) { + if (node == null) { + return; + } + + solution(node.left, n); + solution(node.right, n); + + if (count++ == n) { + System.out.println(node.val); + } + } + +} diff --git a/src/dami/codinginterview/tree/Tree1_1.java b/src/dami/codinginterview/tree/Tree1_1.java new file mode 100644 index 0000000..aab10f0 --- /dev/null +++ b/src/dami/codinginterview/tree/Tree1_1.java @@ -0,0 +1,24 @@ +package dami.codinginterview.tree; + +import dami.codinginterview.common.TreeNode; + +public class Tree1_1 { + public void findTreeDepth(TreeNode node) { + + } + + private int solution(TreeNode node) { + if (node == null) { + return 0; + } + + int leftDepth = solution(node.left); + int rightDepth = solution(node.right); + + if (leftDepth > rightDepth) { + return leftDepth + 1; + } else { + return rightDepth + 1; + } + } +} diff --git a/src/dami/codinginterview/tree/Tree2.java b/src/dami/codinginterview/tree/Tree2.java new file mode 100644 index 0000000..89f9413 --- /dev/null +++ b/src/dami/codinginterview/tree/Tree2.java @@ -0,0 +1,79 @@ +package dami.codinginterview.tree; + +import dami.codinginterview.common.TreeNode; + +import java.util.HashMap; +import java.util.Map; + +// 1. 전위 배열의 첫번째 값은 트리의 루트 노드 값 +// 2. 중위 배열에서 루트 노드 값 위치 찾고, 해당 값 기준 왼쪽은 왼쪽 하위 노드, 오른쪽은 오른쪽 하위 노드 +// 3. 중위 배열 좌, 우 분리해서 재귀 반복 +// 4. 재귀 탈출 조건 : 잘라낸 중위 배열의 start 인덱스와 end 인덱스가 같으면 리프 노드 / start 인덱스 > end 인덱스면 null +public class Tree2 { + private int preIndex = 0; + + // 시간 : O(n^2) + // 공간 : O(n) + public TreeNode makeBinaryTree(int[] inorder, int[] preorder) { + return myRecursive(preorder, inorder, 0, inorder.length - 1); + } + + private TreeNode myRecursive(int[] preorder, int[] inorder, int start, int end) { + if (start == end) { + return new TreeNode(inorder[start]); + } + + if (start > end) { + return null; + } + + TreeNode node = new TreeNode(preorder[preIndex++]); + int inIndex = searchInIndex(inorder, node.val); + + node.left = myRecursive(preorder, inorder, start, inIndex - 1); + node.right = myRecursive(preorder, inorder, inIndex + 1, end); + + return node; + } + + private int searchInIndex(int[] inorder, int value) { + int inIndex = 0; + for (int i = 0; i < inorder.length; i++) { + if (inorder[i] == value) { + inIndex = i; + } + } + return inIndex; + } + + + // 시간 : O(n) + // 공간 : O(n) + private Map inorderMap = new HashMap<>(); + public TreeNode makeBinaryTree_최적화(int[] inorder, int[] preorder) { + for (int i = 0; i < inorder.length; i++) { + inorderMap.put(inorder[i], i); + } + + return recursive(preorder, 0, inorder.length - 1); + } + + private TreeNode recursive(int[] preorder, int start, int end) { + if (start > end) { + return null; + } + + TreeNode node = new TreeNode(preorder[preIndex++]); + + if (start == end) { + return node; + } + + int inIndex = inorderMap.get(node.val); + + node.left = recursive(preorder, start, inIndex - 1); + node.right = recursive(preorder, inIndex + 1, end); + + return node; + } +} diff --git a/src/dami/hackerrank/HackerRank.java b/src/dami/hackerrank/HackerRank.java new file mode 100644 index 0000000..4581c26 --- /dev/null +++ b/src/dami/hackerrank/HackerRank.java @@ -0,0 +1,18 @@ +package dami.hackerrank; + +public class HackerRank { + public void solutions() { + ////////////////////////////////////////////////////////////////////////////// + /* hacker rank */ + //new The_Time_in_Words().timeInWords(12, 50); + //new Highest_Value_Palindrome().highestValuePalindrome("12321", 5, 3); + //new Sherlock_and_the_Valid_String().isValid("aabbcd"); + //new New_Year_Chaos().minimumBribes(new int[] {1, 2, 5, 3, 7, 8, 6, 4}); + //new Minimum_Swaps_2().minimumSwaps(new int[] {4,3,1,2}); + //new Special_StringAgain().substrCount(5, "asasd"); + //new Common_Child().commonChild("WEWOUCUIDGCGTRMEZEPXZFEJWISRSBBSYXAYDFEJJDLEBVHHKS", "FDAGCXGKCTKWNECHMRXZWMLRYUCOCZHJRRJBOAJOQJZZVUYXIC"); + //new Sorting_Comparator().solution(); + //new Fraudulent_Activity_Notifications().activityNotifications(new int[] {10,20,30,40,50}, 3); + ////////////////////////////////////////////////////////////////////////////// + } +} diff --git a/src/dami/hackerrank/medium/Common_Child.java b/src/dami/hackerrank/medium/Common_Child.java new file mode 100644 index 0000000..585e218 --- /dev/null +++ b/src/dami/hackerrank/medium/Common_Child.java @@ -0,0 +1,30 @@ +package dami.hackerrank.medium; + +// https://www.hackerrank.com/challenges/common-child/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=strings + +// LCS 문제 +// 참고 1. https://ko.wikipedia.org/wiki/%EC%B5%9C%EC%9E%A5_%EA%B3%B5%ED%86%B5_%EB%B6%80%EB%B6%84_%EC%88%98%EC%97%B4 +// 참고 2. https://twinw.tistory.com/126 + +// 값 구하는 규칙 +// - String1[n], String2[k]가 같다면 : [n, k] == [n-1, k-1] + 1 +// - String1[n], String2[k]가 다르면 : [n, k] == [n-1, k]와 [n, k-1] 중 큰 값 +public class Common_Child { + public int commonChild(String s1, String s2) { + int[][] lcs = new int[s1.length() + 1][s2.length() + 1]; + + char[] s1c = s1.toCharArray(); + char[] s2c = s2.toCharArray(); + for (int i = 1; i < lcs.length; i++) { + for (int j = 1; j < lcs[0].length; j++) { + if (s2c[i - 1] == s1c[j - 1]) { + lcs[i][j] = lcs[i - 1][j - 1] + 1; + } else { + lcs[i][j] = Math.max(lcs[i - 1][j], lcs[i][j - 1]); + } + } + } + + return lcs[s1.length()][s2.length()]; + } +} diff --git a/src/dami/hackerrank/medium/Minimum_Swaps_2.java b/src/dami/hackerrank/medium/Minimum_Swaps_2.java new file mode 100644 index 0000000..459370d --- /dev/null +++ b/src/dami/hackerrank/medium/Minimum_Swaps_2.java @@ -0,0 +1,68 @@ +package dami.hackerrank.medium; + +import java.util.HashMap; +import java.util.Map; + +// https://www.hackerrank.com/challenges/minimum-swaps-2/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=arrays +public class Minimum_Swaps_2 { + public int minimumSwaps(int[] arr) { + //return timeLimit(arr); + return solution(arr); + } + + // 시간 : O(n) + // 공간 : O(n) + private int solution(int[] arr) { + int count = 0; + + Map numberMap = new HashMap<>(); + for (int i = 0; i < arr.length; i++) { + numberMap.put(arr[i], i); + } + + for (int i = 0; i < arr.length; i++) { + int j = numberMap.get(i + 1); + if (i != j) { + swap(numberMap, arr, i, j); + count++; + } + } + + return count; + } + + + // 시간 : O(n^2) + // 공간 : O(1) + private int timeLimit(int[] arr) { + int count = 0; + + for (int i = 0; i < arr.length - 1; i++) { + int minIndex = i; + for (int j = minIndex + 1; j < arr.length; j++) { + if (arr[minIndex] > arr[j]) { + minIndex = j; + } + } + + if (minIndex != i) { + swap(arr, i, minIndex); + count++; + } + } + + return count; + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + private void swap(Map numberMap, int[] arr, int i, int j) { + swap(arr, i, j); + numberMap.put(arr[i], i); + numberMap.put(arr[j], j); + } +} diff --git a/src/dami/hackerrank/medium/Sherlock_and_the_Valid_String.java b/src/dami/hackerrank/medium/Sherlock_and_the_Valid_String.java new file mode 100644 index 0000000..3c5a72a --- /dev/null +++ b/src/dami/hackerrank/medium/Sherlock_and_the_Valid_String.java @@ -0,0 +1,53 @@ +package dami.hackerrank.medium; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +// 1. 문자열 길이만큼 반복하며 각 char을 Map에 저장 +// - key : char값, value : 나온 횟수 +// 2. 각 문자별 문자 개수를 Set에 저장 +// - 모두 같은 개수인 경우 == set size는 1 : YES +// - 다른 문자 개수가 2개 초과인 경우 == set size는 2 초과 == 문자 한개 제거해도 개수 통일 불가능 : NO +// - 다른 문자 개수가 2개인 경우 == set size는 2 +// - 둘 중 하나가 1이고, 1의 빈도수가 1인 경우 : YES +// - 두 값의 차의 절댓값이 1이고, 둘 중 큰 수의 빈도수가 1인 경우 : YES +// - 나머지 케이스 : NO +public class Sherlock_and_the_Valid_String { + + public String isValid(String s) { + Map charsCountMap = getCharsCountMap(s); + Set otherValues = new HashSet<>(charsCountMap.values()); + int otherValueSize = otherValues.size(); + + if (otherValueSize == 1) { + return "YES"; + } + if (otherValueSize > 2) { + return "NO"; + } + + if (otherValues.contains(1) && charsCountMap.values().stream().filter(value -> value == 1).count() == 1) { + return "YES"; + } + int diff = Math.abs((int) otherValues.toArray()[0] - (int) otherValues.toArray()[1]); + int max = Math.max((int) otherValues.toArray()[0], (int) otherValues.toArray()[1]); + if (diff == 1 && charsCountMap.values().stream().filter(value -> value == max).count() == 1) { + return "YES"; + } + + return "NO"; + } + + private Map getCharsCountMap(String s) { + Map charsCountMap = new HashMap<>(); + char[] string = s.toCharArray(); + + for (char c : string) { + charsCountMap.put(c, charsCountMap.getOrDefault(c, 0) + 1); + } + + return charsCountMap; + } +} diff --git a/src/dami/hackerrank/medium/Sorting_Comparator.java b/src/dami/hackerrank/medium/Sorting_Comparator.java new file mode 100644 index 0000000..5090dbc --- /dev/null +++ b/src/dami/hackerrank/medium/Sorting_Comparator.java @@ -0,0 +1,46 @@ +package dami.hackerrank.medium; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Scanner; + +public class Sorting_Comparator { + public void solution() { + Scanner scan = new Scanner(System.in); + int n = scan.nextInt(); + + Player[] player = new Player[n]; + Checker checker = new Checker(); + + for(int i = 0; i < n; i++){ + player[i] = new Player(scan.next(), scan.nextInt()); + } + scan.close(); + + Arrays.sort(player, checker); + for (Player value : player) { + System.out.printf("%s %s\n", value.name, value.score); + } + } +} + +class Player { + String name; + int score; + + Player(String name, int score) { + this.name = name; + this.score = score; + } +} + +class Checker implements Comparator { + // complete this method + public int compare(Player a, Player b) { + if (a.score == b.score) { + return a.name.compareTo(b.name); + } + + return b.score - a.score; + } +} diff --git a/src/dami/hackerrank/medium/Special_StringAgain.java b/src/dami/hackerrank/medium/Special_StringAgain.java new file mode 100644 index 0000000..a6e0f66 --- /dev/null +++ b/src/dami/hackerrank/medium/Special_StringAgain.java @@ -0,0 +1,42 @@ +package dami.hackerrank.medium; + +// https://www.hackerrank.com/challenges/special-palindrome-again/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=strings +public class Special_StringAgain { + // 재귀 풀이 : 스택오버플로우 발생 + private long count = 0L; + + public long substrCount(int n, String s) { + for (int i = 0; i < n; i++) { + recursive(s.substring(i, i + 1), s, i, i + 1); + } + return count; + } + + private void recursive(String prefix, String s, int start, int end) { + if (isSpecial(prefix)) { + count++; + } + + if (end == s.length()) { + return; + } + + recursive(s.substring(start, ++end), s, start, end); + } + + private boolean isSpecial(String prefix) { + char[] charArray = prefix.toCharArray(); + + char result = charArray[0]; + int index = 0; + for (int i = 1; i < charArray.length; i++) { + if (result != charArray[i]) { + index = i; + } + } + + return index == 0 || (charArray.length % 2 != 0 && index == charArray.length / 2); + } + +} + diff --git a/src/dami/hackerrank/medium/The_Time_in_Words.java b/src/dami/hackerrank/medium/The_Time_in_Words.java new file mode 100644 index 0000000..706559c --- /dev/null +++ b/src/dami/hackerrank/medium/The_Time_in_Words.java @@ -0,0 +1,48 @@ +package dami.hackerrank.medium; + +import java.util.HashMap; +import java.util.Map; + +public class The_Time_in_Words { + private static final String O_CLOCK = " o' clock"; + private static final String MINUTES = " minutes"; + private static final String TO = " to "; + private static final String PAST = " past "; + private static final Map intToWordMap = new HashMap<>(); + + static { + intToWordMap.put(1, "one"); intToWordMap.put(2, "two"); intToWordMap.put(3, "three"); + intToWordMap.put(4, "four"); intToWordMap.put(5, "five"); intToWordMap.put(6, "six"); + intToWordMap.put(7, "seven"); intToWordMap.put(8, "eight"); intToWordMap.put(9, "nine"); + intToWordMap.put(10, "ten"); intToWordMap.put(11, "eleven"); intToWordMap.put(12, "twelve"); + intToWordMap.put(13, "thirteen"); intToWordMap.put(14, "fourteen"); intToWordMap.put(15, "quarter"); + intToWordMap.put(16, "sixteen"); intToWordMap.put(17, "seventeen"); intToWordMap.put(18, "eighteen"); + intToWordMap.put(19, "nineteen"); intToWordMap.put(20, "twenty"); intToWordMap.put(21, "twenty one"); + intToWordMap.put(22, "twenty two"); intToWordMap.put(23, "twenty three"); intToWordMap.put(24, "twenty four"); + intToWordMap.put(25, "twenty five"); intToWordMap.put(26, "twenty six"); intToWordMap.put(27, "twenty seven"); + intToWordMap.put(28, "twenty eight"); intToWordMap.put(29, "twenty nine"); intToWordMap.put(30, "half"); + } + + public String timeInWords(int h, int m) { + if (m == 0) { + return intToWordMap.get(h) + O_CLOCK; + } + + boolean isOver30 = false; + if (m > 30) { + isOver30 = true; + h = (h + 1) % 12; + m = 60 - m; + } + + if (isOver30) { + return intToWordMap.get(m) + getMinutes(m) + TO + intToWordMap.get(h); + } + + return intToWordMap.get(m) + getMinutes(m) + PAST + intToWordMap.get(h); + } + + private String getMinutes(int m) { + return ((m != 15 && m != 30) ? m == 1 ? MINUTES.substring(0, MINUTES.length()-1) : MINUTES : ""); + } +} diff --git a/src/dami/hackerrank/medium/review/Fraudulent_Activity_Notifications.java b/src/dami/hackerrank/medium/review/Fraudulent_Activity_Notifications.java new file mode 100644 index 0000000..05b3b75 --- /dev/null +++ b/src/dami/hackerrank/medium/review/Fraudulent_Activity_Notifications.java @@ -0,0 +1,115 @@ +package dami.hackerrank.medium.review; + +import java.util.PriorityQueue; + +// https://www.hackerrank.com/challenges/fraudulent-activity-notifications/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=sorting&h_r=next-challenge&h_v=zen +// counting sort 사용하기 +public class Fraudulent_Activity_Notifications { + private static final int MAX_VALUE = 201; + + public int activityNotifications(int[] expenditure, int d) { + int[] counting = new int [MAX_VALUE]; + for (int i = 0; i < d; i++) { + counting[expenditure[i]]++; + } + + int result = 0; + for (int i = d; i < expenditure.length; i++) { + double median = findMedian(counting, d); + if (median * 2 <= expenditure[i]) { + result++; + } + + counting[expenditure[i]]++; + counting[expenditure[i - d]]--; + } + + return result; + } + + private double findMedian(int[] counting, int d) { + double median = 0; + int count = 0; + + if (d % 2 == 0) { + int left = 0; + int right = 0; + for (int i = 0; i < counting.length; i++) { + count += counting[i]; + if (count >= d / 2) { + left = i; + } else if (count >= d / 2 + 1) { + right = i; + break; + } + } + median = (left + right) / 2.0; + + } else { + for (int i = 0; i < counting.length; i++) { + count += counting[i]; + if (count > d / 2) { + median = i; + break; + } + } + } + return median; + } + + + + // O(n) + private int[] countingSort(int[] expenditure, int start, int d) { + int[] sorted = new int[d]; + int[] counting = new int [MAX_VALUE]; + for (int i = start; i < start + d; i++) { + counting[expenditure[i]]++; + } + for (int i = 1; i < counting.length; i++) { + counting[i] += counting[i - 1]; + } + for (int i = start; i < start + d; i++) { + sorted[--counting[expenditure[i]]] = expenditure[i]; + } + return sorted; + } + + /* // timeout + public int activityNotifications(int[] expenditure, int d) { + PriorityQueue trailingDays = new PriorityQueue<>(); + for (int i = 0; i < d; i++) { + trailingDays.offer(expenditure[i]); + } + + int result = 0; + for (int i = d; i < expenditure.length; i++) { + int median = findMedian(new PriorityQueue<>(trailingDays), trailingDays.size()); + if (median * 2 <= expenditure[i]) { + result++; + } + + trailingDays.poll(); + trailingDays.offer(expenditure[i]); + } + + return result; + } + + private int findMedian(PriorityQueue trailingDays, int size) { + int mid = size / 2; + + while (mid != 0) { + trailingDays.poll(); + mid--; + } + + + if (size % 2 == 0) { + return (trailingDays.poll() + trailingDays.poll()) / 2; + } else { + return trailingDays.poll(); + } + } + */ +} diff --git a/src/dami/hackerrank/medium/review/Highest_Value_Palindrome.java b/src/dami/hackerrank/medium/review/Highest_Value_Palindrome.java new file mode 100644 index 0000000..ff3aece --- /dev/null +++ b/src/dami/hackerrank/medium/review/Highest_Value_Palindrome.java @@ -0,0 +1,77 @@ +package dami.hackerrank.medium.review; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +// https://www.hackerrank.com/challenges/richie-rich/problem +public class Highest_Value_Palindrome { + private static final String pattern = Pattern.compile("[0-9]").pattern(); + private static final char MAX = '9'; + + public String highestValuePalindrome(String s, int n, int k) { + if (n <= k) { + return s.replaceAll(pattern, "9"); + } + + char[] chars = s.toCharArray(); + List diff = differentIndexes(chars); + + if (k < diff.size()) { + return "-1"; + } + + // 양쪽 다른 숫자 치환 + int diffSize = diff.size(); + for (int i = 0; i < diff.size() && k > 0; i++) { + char m; + if (k > diffSize) { + m = MAX; // 변경 횟수 충분하면 양쪽 최댓값 9로 치환 + } else { + m = (char) Math.max(chars[diff.get(i)], chars[chars.length - diff.get(i) - 1]); + } + + if (chars[diff.get(i)] != m) { + chars[diff.get(i)] = m; + k--; + } + + if (chars[chars.length - diff.get(i) - 1] != m) { + chars[chars.length - diff.get(i) - 1] = m; + k--; + } + + diffSize--; + } + + // 양쪽 같은 숫자 최댓값 9로 치환 + for (int i = 0; i < n / 2 && k > 0; i++) { + if (k == 1 && n % 2 != 0) { + chars[chars.length / 2] = MAX; + k--; + } else { + if (chars[i] != MAX) { + chars[i] = MAX; + k--; + } + + if (chars[chars.length - i - 1] != MAX) { + chars[chars.length - i - 1] = MAX; + k--; + } + } + } + + return new String(chars); + } + + private List differentIndexes(char[] chars) { + List diff = new ArrayList<>(); + for (int i = 0; i < chars.length / 2; i++) { + if (chars[i] != chars[chars.length - i - 1]) { + diff.add(i); + } + } + return diff; + } +} diff --git a/src/dami/hackerrank/medium/review/New_Year_Chaos.java b/src/dami/hackerrank/medium/review/New_Year_Chaos.java new file mode 100644 index 0000000..ccd7c57 --- /dev/null +++ b/src/dami/hackerrank/medium/review/New_Year_Chaos.java @@ -0,0 +1,30 @@ +package dami.hackerrank.medium.review; + +// https://www.hackerrank.com/challenges/new-year-chaos/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=arrays + +// 현재 위치 : 1 2 5 3 7 8 6 4 +// 처음 위치 : 1 2 3 4 5 6 7 8 +// 위치 차이 : 0 0 2 -1 2 2 -1 -4 +// 1. 이동 수(위치 차이)가 2보다 큰 경우는 chaotic +// 2. 현재 값이 원래 있어야 할 위치 - 2부터 현재 값 위치까지 반복하면서 현재 값보다 큰 수 있으면 count++ (뒤로 밀어주는 것) +// ⭐️뒤 부터 반복 +public class New_Year_Chaos { + + public void minimumBribes(int[] q) { + int count = 0; + for (int i = q.length - 1; i >= 0; i--) { + if (q[i] - (i + 1) > 2) { + System.out.println("Too chaotic"); + return; + } + + for (int j = Math.max(0, q[i] - 2); j < i; j++) { + if (q[j] > q[i]) { + count++; + } + } + } + System.out.println(count); + } + +} diff --git a/src/dami/leetcode/Leetcode.java b/src/dami/leetcode/Leetcode.java new file mode 100644 index 0000000..5b33218 --- /dev/null +++ b/src/dami/leetcode/Leetcode.java @@ -0,0 +1,47 @@ +package dami.leetcode; + +public class Leetcode { + public void solutions() { + ////////////////////////////////////////////////////////////////////////////// + /* easy */ + //new Two_Sum_1().twoSum(new int[] {2, 7, 11, 15}, 9); + /* + new Add_Two_Numbers_2().addTwoNumbers( + new ListNode(2, new ListNode(4, new ListNode(3, null))), + new ListNode(5, new ListNode(6, new ListNode(4, null)))); + */ + //new Reverse_Integer_7().reverse(-123); + //new Palindrome_Number_9().isPalindrome(1000000001); + //new Roman_to_Integer_13().romanToInt("MMMCMXCIX"); + //new Longest_Common_Prefix_14().longestCommonPrefix(new String[]{"dog", "racecar", "car"}); + ////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////// + /* medium */ + //SubrectangleQueries s = new SubrectangleQueries(new int[][] {{1,2,1},{4,3,4},{3,2,1},{1,1,1}}); + //s.updateSubrectangle(0, 0, 3, 2, 5); + //s.getValue(2, 2); + //new Partition_Labels_763().partitionLabels("befrppytljbvezqkjzkvmncnc"); // "ababcbacadefegdehijhklij" + //new Add_Two_Numbers_2(); + //new Longest_Substring_3().lengthOfLongestSubstring("abcabcbb"); // "abcabcbb", "bbbbb", "pwwkew", " ", "dvdf", "abcb" + //new Group_Anagrams_49().groupAnagrams(new String[] {"eat","tea","tan","ate","nat","bat"}); + //new Container_With_Most_Water_11().maxArea(new int[]{1, 8, 6, 2, 5, 4, 8, 3, 7}); + //new Letter_Combinations_17().letterCombinations("234"); + //new Generate_Parentheses_22().generateParenthesis(3); + //new Remove_Nth_Node_19().removeNthFromEnd(new ListNode(), 1); + //new Permutations_46().permute(new int[] {1,2,3}); + //new Combination_Sum_39().combinationSum(new int[] {2,3,5}, 8); + //new Queue_Reconstruction_406().reconstructQueue(new int[][]{{7,0}, {4,4}, {7,1}, {5,0}, {6,1}, {5,2}}); + //new Counting_Bits_338().countBits(5); + //new Longest_Palindromic_Substring_5().longestPalindrome("abcdccbc"); + //new Binary_Tree_Inorder_94().inorderTraversal(null); + //new Subsets_78().subsets(new int[] {1, 2, 3}); + //new Daily_Temperatures_739().dailyTemperatures(new int[] {73, 74, 75, 71, 69, 72, 76, 73}); + //new Top_K_Frequent_Elements_347().topKFrequent(new int[] {1,1,1,2,2,3,5}, 2); + //new Kth_Smallest_Element_230().kthSmallest(new TreeNode(3, new TreeNode(2), new TreeNode(4, null, new TreeNode(7))), 1); + ////////////////////////////////////////////////////////////////////////////// + + + //new Three_Sum_15().threeSum(new int[]{-1, 0, 1, 2, -1, -4}); + } +} diff --git a/src/dami/leetcode/common/ListNode.java b/src/dami/leetcode/common/ListNode.java new file mode 100644 index 0000000..23b437f --- /dev/null +++ b/src/dami/leetcode/common/ListNode.java @@ -0,0 +1,17 @@ +package dami.leetcode.common; + +public class ListNode { + public int val; + public ListNode next; + + public ListNode() { } + + public ListNode(int val) { + this.val = val; + } + + public ListNode(int val, ListNode next) { + this.val = val; + this.next = next; + } +} diff --git a/src/dami/leetcode/common/TreeNode.java b/src/dami/leetcode/common/TreeNode.java new file mode 100644 index 0000000..f09bc00 --- /dev/null +++ b/src/dami/leetcode/common/TreeNode.java @@ -0,0 +1,14 @@ +package dami.leetcode.common; + +public class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + public TreeNode() {} + public TreeNode(int val) { this.val = val; } + public TreeNode(int val, TreeNode left, TreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } +} diff --git a/src/dami/leetcode/easy/Longest_Common_Prefix_14.java b/src/dami/leetcode/easy/Longest_Common_Prefix_14.java new file mode 100644 index 0000000..d6e21bf --- /dev/null +++ b/src/dami/leetcode/easy/Longest_Common_Prefix_14.java @@ -0,0 +1,48 @@ +package dami.leetcode.easy; + +import java.util.Arrays; +import java.util.Comparator; + +// 1. 주어진 배열에서 가장 짧은 단어 추출 +// 2. 가장 짧은 단어 길이만큼 반복 +// - 가장 짧은 단어 앞에서부터 한 개씩 substring 하고 나머지 배열 값 중 같은 문자열 개수 확인 +// - 같은 문자열 개수가 3개 미만이면 이전 문자까지 자른 prefix 반환 +// 3. 반복문 끝까지 같은 문자열 개수 3개이면 가장 짧은 문자열 반환 +public class Longest_Common_Prefix_14 { + public String longestCommonPrefix(String[] strs) { + String shortestWord = shortestWordInArray(strs); + for (int i = 1; i <= shortestWord.length(); i++) { + String substring = shortestWord.substring(0, i); + long count = Arrays.stream(strs) + .filter(str -> str.startsWith(substring)) + .count(); + if (count != strs.length) { + return substring.substring(0, i-1); + } + } + return shortestWord; + } + + private String shortestWordInArray(String[] strs) { + return Arrays.stream(strs) + .min(Comparator.comparing(String::length)) + .orElse(""); + } +} + + +/* + // 빠른 속도 답 + if(strs.length == 0) return ""; + + for(int i = 0; i= 1) { + remainder = quotient % DIVIDING_NUMBER; + quotient = quotient / DIVIDING_NUMBER; + + reversedX = (reversedX + remainder) * DIVIDING_NUMBER; + } + + return (int) (reversedX / DIVIDING_NUMBER); + } +} diff --git a/src/dami/leetcode/easy/Reverse_Integer_7.java b/src/dami/leetcode/easy/Reverse_Integer_7.java new file mode 100644 index 0000000..4597cc9 --- /dev/null +++ b/src/dami/leetcode/easy/Reverse_Integer_7.java @@ -0,0 +1,58 @@ +package dami.leetcode.easy; + +// Submission Detail : https://leetcode.com/submissions/detail/356536589/ +public class Reverse_Integer_7 { + + public int reverse(int x) { + try { + long result = 0; + int n = 0; + while(x != 0) { + n = x%10; + result += n; + x = (x-n)/10; + + if(x != 0) { + if(result*10 <= Integer.MAX_VALUE && result*10 >= Integer.MIN_VALUE) + result *= 10; + else + return 0; + } + } + return (int) result; + + } catch(NumberFormatException e) { + return 0; + } catch(ArithmeticException e) { + return 0; + } + } +} + +/* +class Solution { + public int reverse(int x) { + + int result = 0; + + while (x != 0) { + + int pop = x % 10; + + x = x / 10; + + if (result > Integer.MAX_VALUE / 10) { + return 0; + } + + if (result < Integer.MIN_VALUE / 10) { + return 0; + } + + result = result * 10 + pop; + } + + return result; + } +} + */ diff --git a/src/dami/leetcode/easy/Roman_to_Integer_13.java b/src/dami/leetcode/easy/Roman_to_Integer_13.java new file mode 100644 index 0000000..5346631 --- /dev/null +++ b/src/dami/leetcode/easy/Roman_to_Integer_13.java @@ -0,0 +1,37 @@ +package dami.leetcode.easy; + +import java.util.HashMap; +import java.util.Map; + +// 테스트 케이스 +// "I", "III", "IV", "IX", "LVIII", "MCMXCIV", "MMMCMXCIX" +public class Roman_to_Integer_13 { + private final static Map romanMap = new HashMap<>(); + + static { + romanMap.put("I", 1); + romanMap.put("V", 5); + romanMap.put("X", 10); + romanMap.put("L", 50); + romanMap.put("C", 100); + romanMap.put("D", 500); + romanMap.put("M", 1000); + } + + public int romanToInt(String s) { + int sum = 0; + for (int i = 0; i < s.length(); i++) { + int current = romanMap.get(String.valueOf(s.charAt(i))); + int next = i+1 == s.length() ? 0 : romanMap.get(String.valueOf(s.charAt(i+1))); + + if (current < next) { + sum += next - current; + i++; + continue; + } + sum += current; + } + + return sum; + } +} diff --git a/src/dami/leetcode/easy/Two_Sum_1.java b/src/dami/leetcode/easy/Two_Sum_1.java new file mode 100644 index 0000000..7e9c869 --- /dev/null +++ b/src/dami/leetcode/easy/Two_Sum_1.java @@ -0,0 +1,17 @@ +package dami.leetcode.easy; + +// Submission Detail : https://leetcode.com/submissions/detail/356520239/ +public class Two_Sum_1 { + + public int[] twoSum(int[] nums, int target) { + for(int i=0; i 0) { + newNode.next = new ListNode(1); + } + + return result; + } +} diff --git a/src/dami/leetcode/medium/Combination_Sum_39.java b/src/dami/leetcode/medium/Combination_Sum_39.java new file mode 100644 index 0000000..a9cab5e --- /dev/null +++ b/src/dami/leetcode/medium/Combination_Sum_39.java @@ -0,0 +1,82 @@ +package dami.leetcode.medium; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// https://leetcode.com/problems/combination-sum/ + +public class Combination_Sum_39 { + private List> result; + + public List> combinationSum(int[] candidates, int target) { + Arrays.sort(candidates); + + result = new ArrayList<>(); + recursive(new ArrayList<>(), candidates, target, 0, 0); + + return result; + } + + private void recursive(List candidate, int[] candidates, int target, int sum, int index) { + if (sum == target) { + result.add(new ArrayList<>(candidate)); + return; + } + + for (int i = index; i < candidates.length && candidates[i] <= target; i++) { + if (sum + candidates[i] > target) { + break; + } + candidate.add(candidates[i]); + recursive(candidate, candidates, target, sum + candidates[i], index++); + candidate.remove(candidate.size() - 1); + } + } + + /* + private void recursive2(List candidate, int[] candidates, int target, int index) { + if (target == 0) { + result.add(new ArrayList<>(candidate)); + return; + } + + for (int i = index; i < candidates.length && candidates[i] <= target; i++) { + if (target - candidates[i] > target) { + break; + } + candidate.add(candidates[i]); + recursive2(candidate, candidates,target - candidates[i], index++); + candidate.remove(candidate.size() - 1); + } + } + */ +} + + +/* + +// 합한 값이 아니라 target에서 candidates[i] 값 빼서 최종 target == 0으로 비교하면 재귀 메소드 인자 한 개 줄이기 가능 +// recursive2가 참고해서 인자 수 줄인 메소드 + +public List> combinationSum(int[] candidates, int target) { + List> result = new ArrayList<>(); + helper(result,candidates,new ArrayList<>(),target,0); + return result; +} + void helper(List> result, int[] candidates, List temp, int target,int index) { + if(target == 0) { + result.add(new ArrayList<>(temp)); + return; + } + for(int i = index; i < candidates.length; i++) { + if(candidates[i] <= target) { + temp.add(candidates[i]); + helper(result,candidates,temp,target-candidates[i],i); + temp.remove(temp.size()-1); + } + } +} + +*/ diff --git a/src/dami/leetcode/medium/Container_With_Most_Water_11.java b/src/dami/leetcode/medium/Container_With_Most_Water_11.java new file mode 100644 index 0000000..b573c63 --- /dev/null +++ b/src/dami/leetcode/medium/Container_With_Most_Water_11.java @@ -0,0 +1,61 @@ +package dami.leetcode.medium; + +// https://leetcode.com/problems/container-with-most-water/ + +// 1. 가장자리 인덱스부터 시작 +// 2. 왼쪽 인덱스와 오른쪽 인덱스가 다를 때까지 34 반복 +// 3. (뒷 인덱스 - 앞 인덱스) * min(앞 값, 뒷 값) +// 4. 둘 중 작은값을 가지는 인덱스를 안쪽으로 이동(-> <-) +// - 작은값보다 큰값이 나올 때까지 && 큰값인덱스랑 같기 전까지 +// 5. 34 반복 하면서 가장 큰 2번값 찾아서 반환 +public class Container_With_Most_Water_11 { + public int maxArea(int[] height) { + int max = 0; + int left = 0; + int right = height.length - 1; + int minIndex; + while (left != right) { + max = Math.max(max, (right - left) * Math.min(height[left], height[right])); + + if (height[left] < height[right]) { + minIndex = left; + while (height[minIndex] >= height[left] && left < right) { + left++; + } + } else { + minIndex = right; + while (height[minIndex] >= height[right] && left < right) { + right--; + } + } + } + + return max; + } +} + +/* +// 아래 풀이는 모든 인덱스마다 넓이 계산해서 비교해줬고 +// 나는 현재 비교한 인덱스의 값보다 작은 값의 넓이는 계산하지 않음 + +// 아래 풀이는 최소값 비교를 한 번만 해줌 +// 나는 while문 들어가자마자 Math.min하고 그 아래 if문에서 또 min 비교 + +public int maxArea(int[] height) { + int ans= 0 ; + int low=0; + int high = height.length-1; + while(low r = new Stack<>(); + r.push(0); + for (int i = 1; i < T.length; i++) { + while (!r.isEmpty() && T[r.peek()] < T[i]) { + int index = r.pop(); + result[index] = i - index; + } + r.push(i); + } + + while (!r.isEmpty()) { + result[r.pop()] = 0; + } + + return result; + } +} + + + +/* +// 시간복잡도 O(n^2), 실행시간 : 1095 ms / 메모리 : 47MB +public int[] dailyTemperatures(int[] T) { + int[] result = new int[T.length]; + for (int i = 0; i < T.length; i++) { + int count = 0; + for (int j = i + 1; j < T.length; j++) { + if (T[i] < T[j]) { + result[i] = count + 1; + break; + } + count++; + } + + if (count + i + 1 == T.length) { + result[i] = 0; + } + } + + return result; +} + +*/ diff --git a/src/dami/leetcode/medium/Generate_Parentheses_22.java b/src/dami/leetcode/medium/Generate_Parentheses_22.java new file mode 100644 index 0000000..fdd68b2 --- /dev/null +++ b/src/dami/leetcode/medium/Generate_Parentheses_22.java @@ -0,0 +1,59 @@ +package dami.leetcode.medium; + +import java.util.ArrayList; +import java.util.List; + +// https://leetcode.com/problems/generate-parentheses/ +public class Generate_Parentheses_22 { + private static final String OPEN = "("; + private static final String CLOSE = ")"; + + private final List result = new ArrayList<>(); + + public List generateParenthesis(int n) { + StringBuilder sb = new StringBuilder(); + recursive(sb, 0, 0, n); + return result; + } + + private void recursive(StringBuilder prefix, int open, int close, int n) { + if (n * 2 == prefix.length()) { + result.add(prefix.toString()); + return; + } + + if (open < n) { + prefix.append(OPEN); + recursive(prefix, open + 1, close, n); + prefix.deleteCharAt(prefix.length() - 1); + } + + if (close < open) { + prefix.append(CLOSE); + recursive(prefix, open, close + 1, n); + prefix.deleteCharAt(prefix.length() - 1); + } + } +} + +/* + +// 나는 0부터 시작해서 n개 까지 진행 +// 아래 코드는 n부터 시작해서 0까지 진행 => 매개변수 한 개(int n) 줄이기 가능 + +public List generateParenthesis(int n) { + List result= new ArrayList(); + dfs(n,n,result,""); + return result; +} + +public void dfs(int left, int right, List result, String s) { + if(left==0 && right==0) result.add(s); + else + { + if(left>0) dfs(left-1, right, result, s+"("); + if(right>left) dfs(left, right-1, result, s+")"); + } +} + +*/ diff --git a/src/dami/leetcode/medium/Group_Anagrams_49.java b/src/dami/leetcode/medium/Group_Anagrams_49.java new file mode 100644 index 0000000..230940a --- /dev/null +++ b/src/dami/leetcode/medium/Group_Anagrams_49.java @@ -0,0 +1,82 @@ +package dami.leetcode.medium; + +import java.util.*; + +// https://leetcode.com/problems/group-anagrams/ +// 주어진 문자열 배열에서 애너그램 그룹핑 해서 반환 + +// 1. 주어진 문자열 배열에서 각 문자열을 오름차순 소팅한 sortedStrs 생성 +// 2. sortedStr을 Key로 하는 Map 생성 +// 3. 주어진 문자열 배열 크기만큼 반복하면서 +// 소팅한 문자열이 맵에 키로 들어가있지 않으면 put +// 키로 들어있으면 해당 문자열은 해당 키의 값 +// 3. map의 values() 반환 + +public class Group_Anagrams_49 { + public List> groupAnagrams(String[] strs) { + if (strs.length == 0) { + return new ArrayList<>(); + } + + Map> result = new HashMap<>(); + for (String s : strs) { + char[] str = s.toCharArray(); + Arrays.sort(str); + + String key = String.valueOf(str); + if (!result.containsKey(key)) { + result.put(key, new ArrayList<>()); + } + result.get(key).add(s); + } + + return new ArrayList<>(result.values()); + } +} + +/* // Stream 활용한 풀이 **Collectors.groupingBy()** + public List> groupAnagrams(String[] strs) { + List> groups = Arrays.asList(strs) + .stream() + .collect(Collectors.groupingBy(word -> { + char[] chars = word.toCharArray(); + Arrays.sort(chars); + return new String(chars); + })) + .values() + .stream() + .collect(Collectors.toList()); + + return groups; + } + +*/ + +/* // 마지막 테스트케이스 타임아웃 발생 + public List> groupAnagrams(String[] strs) { + Map> strGroup = new HashMap<>(); + for (String str : strs) { + String sortedStr = sortString(str); + strGroup.put(sortedStr, sameValues(sortedStr, strs)); + } + return new ArrayList<>(strGroup.values()); + } + + private String sortString(String str) { + char[] chars = str.toCharArray(); + Arrays.sort(chars); + + StringBuilder sb = new StringBuilder(); + for (char c : chars) { + sb.append(c); + } + return sb.toString(); + } + + private List sameValues(String value, String[] strs) { + return Arrays.stream(strs) + .filter(str -> sortString(str).equals(value)) + .collect(Collectors.toList()); + } + +*/ diff --git a/src/dami/leetcode/medium/Kth_Smallest_Element_230.java b/src/dami/leetcode/medium/Kth_Smallest_Element_230.java new file mode 100644 index 0000000..38eebfc --- /dev/null +++ b/src/dami/leetcode/medium/Kth_Smallest_Element_230.java @@ -0,0 +1,68 @@ +package dami.leetcode.medium; + +import dami.leetcode.common.TreeNode; + +import java.util.PriorityQueue; + +// https://leetcode.com/problems/kth-smallest-element-in-a-bst/ +// 1. 트리노드 순회하며 값 모두 꺼내서 우선순위 큐에 추가 +// 2. k만큼 우선순위 큐에서 빼기 +public class Kth_Smallest_Element_230 { + + // 시간 : O(n) + // 공간 : O(n)? O(n^2)? + public int kthSmallest(TreeNode root, int k) { + PriorityQueue tree = new PriorityQueue<>(); + + inorder(tree, root); + + int result = 0; + while (!tree.isEmpty() && k-- > 0) { + result = tree.poll(); + } + + return result; + } + + private void inorder(PriorityQueue tree, TreeNode node) { + if (null == node) { + return; + } + + inorder(tree, node.left); + tree.offer(node.val); + inorder(tree, node.right); + } + +} + +/* // 다른 방법 + // 중위순회랑 동시에 k번째 값 확인 가능 + // ⭐️⭐️ 이진탐색 트리는 중위순회 순서상 가장 먼저 조회하는 값이 가장 작은 값 + // 조회 순서 == 노드 값 오름차순 + +public class Kth_Smallest_Element_230 { + int count = 0, val; + + public int kthSmallest(TreeNode root, int k) { + visit(root, k); + return val; + } + + + // in order visit + private void visit(TreeNode root, int k) { + if(root == null || val > 0) { + return; + } + + visit(root.left, k); + + if(++count == k) { + val = root.val; + } + + visit(root.right, k); + } +} +*/ diff --git a/src/dami/leetcode/medium/Letter_Combinations_17.java b/src/dami/leetcode/medium/Letter_Combinations_17.java new file mode 100644 index 0000000..13d6d40 --- /dev/null +++ b/src/dami/leetcode/medium/Letter_Combinations_17.java @@ -0,0 +1,75 @@ +package dami.leetcode.medium; + +import java.util.*; + +// https://leetcode.com/problems/letter-combinations-of-a-phone-number/ +// 3가지 방법으로 구현 +public class Letter_Combinations_17 { + private static final String[] DIGIT_TO_LETTERS = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; + + public List letterCombinations(String digits) { + if (digits.length() == 0) { + return new ArrayList<>(); + } + + // bfsCombination1과 2는 같은 시간복잡도 + List bfsResult1 = bfsCombination1(digits); + List bfsResult2 = bfsCombination2(digits); + List recursiveResult = new ArrayList<>(); + recursiveDfsCombination(recursiveResult, digits, new StringBuilder(), 0); + + return bfsResult1; + } + + // 방법 1, 반복문 BFS + // 같은 레벨 모두 순회 후 다음 레벨 순회 + // Queue에서 꺼내 문자열 더하고 다시 add + private List bfsCombination1(String digits) { + LinkedList result = new LinkedList<>(); + result.add(""); + + for (int i = 0; i < digits.length(); i++) { + int number = Character.getNumericValue(digits.charAt(i)); + while (result.peek().length() == i) { + String combi = result.poll(); + for (char c : DIGIT_TO_LETTERS[number].toCharArray()) { + result.add(combi + c); + } + } + } + + return result; + } + + // 방법 2, 반복문 BFS + private List bfsCombination2(String digits) { + LinkedList result = new LinkedList<>(); + result.add(""); + + while (result.peek().length() != digits.length()) { + String combi = result.poll(); + String mapLetter = DIGIT_TO_LETTERS[digits.charAt(combi.length()) - '0']; // 조합한 문자 길이값의 위치에 있는 digit과 매핑되는 문자열 + for (char c : mapLetter.toCharArray()) { + result.addLast(combi + c); + } + + } + + return result; + } + + // 방법 3, 재귀 DFS + private void recursiveDfsCombination(List result, String digits, StringBuilder combi, int offset) { + if (offset == digits.length()) { + result.add(combi.toString()); + return; + } + + int number = digits.charAt(offset) - '0'; + for (int i = 0; i < DIGIT_TO_LETTERS[number].length(); i++) { + combi.append(DIGIT_TO_LETTERS[number].charAt(i)); + recursiveDfsCombination(result, digits, combi, offset + 1); + combi.deleteCharAt(combi.length() - 1); + } + } +} diff --git a/src/dami/leetcode/medium/Longest_Substring_3.java b/src/dami/leetcode/medium/Longest_Substring_3.java new file mode 100644 index 0000000..d6dad78 --- /dev/null +++ b/src/dami/leetcode/medium/Longest_Substring_3.java @@ -0,0 +1,78 @@ +package dami.leetcode.medium; + +import java.util.*; + +// https://leetcode.com/problems/longest-substring-without-repeating-characters/ +// 주어진 문자열에서 가장 긴 중복 없는 문자열 길이 구하기 +// 영문자, 숫자, 특수문자, 스페이스 공백 포함 + +// 1. 주어진 문자열을 char array로 분리 +// 2. array만큼 반복하면서 List에 추가하기 전에 List에 현재값 있는지 확인 +// 없으면 List에 추가 +// 있으면 현재위치까지 문자열 길이 계산해서 최댓값 비교 + +// 처음에는 중복 문자까지 리스트를 자를 때 charList = subList로 했는데 속도가 매우 느렸음 1668ms..ㄷㄷ +// 찾아보니 subList할 때는 new ArrayList<>(subList);를 해야 속도 개선 가능 +// [참고] https://m.blog.naver.com/PostView.nhn?blogId=yjw2288&logNo=221072561904&proxyReferer=https:%2F%2Fwww.google.com%2F +// 변경 후 11ms로 줄었지만.. 그래도 느림 +// 가장 빠른 방법은 하단 다른 풀이 1, 2 확인 +public class Longest_Substring_3 { + public int lengthOfLongestSubstring(String s) { + int max = 0; + char[] string = s.toCharArray(); + List charList = new ArrayList<>(); + for (char c : string) { + if (!charList.contains(c)) { + charList.add(c); + max = Math.max(max, charList.size()); + continue; + } + + int length = charList.indexOf(c) + 1; // 0부터 중복값 index까지 길이이자 다음 문자열의 offset + charList.add(c); + charList = new ArrayList<>(charList.subList(length, charList.size())); + max = Math.max(max, length); + } + + return max; + } +} + +/* // 다른 풀이 1 + public int lengthOfLongestSubstring(String s) { + if(s==null || s.length()==0) + return 0; + int maxL=1; + int start =0; + char [] arr = s.toCharArray(); + for(int end=0;end result = new ArrayList<>(); + + public List partitionLabels(String S) { + Set characters = this.distinct(S); + Iterator iter = characters.iterator(); + + char next = iter.next(); + int firstIndex = S.indexOf(next); + int lastIndex = S.lastIndexOf(next); + + while (iter.hasNext()) { + char current = next; + next = iter.next(); + + // 현재 문자의 마지막 인덱스와 이전 문자의 마지막 인덱스 비교 + lastIndex = Math.max(lastIndex, S.lastIndexOf(current)); + // 다음 문자의 첫번째 인덱스와 가장 큰 마지막 인덱스 + 1이 같으면 + // 문자열 파티션 + if (S.indexOf(next) == lastIndex + 1) { + result.add(lastIndex - firstIndex + 1); + firstIndex = S.indexOf(next); + lastIndex = S.lastIndexOf(next); + } + } + + // Set의 마지막 문자의 마지막 인덱스는 반복문 내에서 확인할 수 없기 때문에 반복문 종료 후 한 번 더 확인 + lastIndex = Math.max(lastIndex, S.lastIndexOf(next)); + if (S.length() - 1 > lastIndex) { + result.add(lastIndex - firstIndex + 1); + result.add(S.length() - (lastIndex - firstIndex + 1)); + } else { + result.add(S.length() - firstIndex); + } + + return result; + } + + private Set distinct(String s) { + Set set = new LinkedHashSet<>(); + char[] string = s.toCharArray(); + for (char c : string) { + set.add(c); + } + return set; + } +} + +/* + public List partitionLabels(String S) { + int[] last = new int[26]; + for (int i = 0; i < S.length(); ++i) + last[S.charAt(i) - 'a'] = i; + + int j = 0, anchor = 0; + List ans = new ArrayList(); + for (int i = 0; i < S.length(); ++i) { + j = Math.max(j, last[S.charAt(i) - 'a']); + if (i == j) { + ans.add(i - anchor + 1); + anchor = i + 1; + } + } + return ans; + } +*/ diff --git a/src/dami/leetcode/medium/Permutations_46.java b/src/dami/leetcode/medium/Permutations_46.java new file mode 100644 index 0000000..58f1187 --- /dev/null +++ b/src/dami/leetcode/medium/Permutations_46.java @@ -0,0 +1,37 @@ +package dami.leetcode.medium; + +import java.util.ArrayList; +import java.util.List; + +// https://leetcode.com/problems/permutations/ + +// 순열 알고리즘 연습 +public class Permutations_46 { + public List> permute(int[] nums) { + List> result = new ArrayList<>(); + recursive(result, nums, new ArrayList<>(), 0); + + return result; + } + + private void recursive(List> result, int[] nums, List perms, int depth) { + if (depth == nums.length) { + result.add(new ArrayList<>(perms)); + return; + } + + for (int i = depth; i < nums.length; i++) { + perms.add(nums[i]); + swap(nums, i, depth); + recursive(result, nums, perms, depth + 1); + perms.remove(perms.size() - 1); + swap(nums, i, depth); + } + } + + private void swap(int[] nums, int index, int depth) { + int temp = nums[index]; + nums[index] = nums[depth]; + nums[depth] = temp; + } +} diff --git a/src/dami/leetcode/medium/Remove_Nth_Node_19.java b/src/dami/leetcode/medium/Remove_Nth_Node_19.java new file mode 100644 index 0000000..51bf474 --- /dev/null +++ b/src/dami/leetcode/medium/Remove_Nth_Node_19.java @@ -0,0 +1,43 @@ +package dami.leetcode.medium; + +import dami.leetcode.common.ListNode; + +// https://leetcode.com/problems/remove-nth-node-from-end-of-list/ +// 다른 코드 : https://leetcode.com/submissions/detail/431959305/ + +public class Remove_Nth_Node_19 { + public ListNode removeNthFromEnd(ListNode head, int n) { + // head = new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(5))))); + // head = new ListNode(1); + + int listSize = sizeOf(head); + ListNode current = head; + if (n == listSize) { // 첫번째 노드일 때 + head = current.next; + + } else if (n == 1) { // 마지막 노드일 때 + for (int i = 0; i < listSize - 2; i++) { + current = current.next; + } + current.next = null; + + } else { // 중간 노드 + for (int i = 0; i < listSize - n - 1; i++) { + current = current.next; + } + current.next = current.next.next; + } + + return head; + } + + private int sizeOf(ListNode head) { + int size = 0; + ListNode list = head; + while (list != null) { + list = list.next; + size++; + } + return size; + } +} diff --git a/src/dami/leetcode/medium/SubrectangleQueries.java b/src/dami/leetcode/medium/SubrectangleQueries.java new file mode 100644 index 0000000..adeb39b --- /dev/null +++ b/src/dami/leetcode/medium/SubrectangleQueries.java @@ -0,0 +1,21 @@ +package dami.leetcode.medium; + +public class SubrectangleQueries { + private final int[][] rectangle; + + public SubrectangleQueries(int[][] rectangle) { + this.rectangle = rectangle; + } + + public void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) { + for (int i = row1; i <= row2 ; i++) { + for (int j = col1; j <= col2; j++) { + rectangle[i][j] = newValue; + } + } + } + + public int getValue(int row, int col) { + return rectangle[row][col]; + } +} diff --git a/src/dami/leetcode/medium/Subsets_78.java b/src/dami/leetcode/medium/Subsets_78.java new file mode 100644 index 0000000..22d056e --- /dev/null +++ b/src/dami/leetcode/medium/Subsets_78.java @@ -0,0 +1,23 @@ +package dami.leetcode.medium; + +import java.util.ArrayList; +import java.util.List; + +// https://leetcode.com/problems/subsets/ +public class Subsets_78 { + public List> subsets(int[] nums) { + List> result = new ArrayList<>(); + recursive(result, new ArrayList<>(), nums, 0); + return result; + } + + private void recursive(List> result, List set, int[] nums, int start) { + result.add(new ArrayList<>(set)); + + for (int i = start; i < nums.length; i++) { + set.add(nums[i]); + recursive(result, set, nums, i + 1); + set.remove(set.size() - 1); + } + } +} diff --git a/src/dami/leetcode/medium/Three_Sum_15.java b/src/dami/leetcode/medium/Three_Sum_15.java new file mode 100644 index 0000000..fc0ad9e --- /dev/null +++ b/src/dami/leetcode/medium/Three_Sum_15.java @@ -0,0 +1,34 @@ +package dami.leetcode.medium; + +import java.util.*; +import java.util.stream.Collectors; + +// https://leetcode.com/problems/3sum/ +public class Three_Sum_15 { + private static final int TARGET = 0; + + // {-1, 0, 1, 2, -1, -4} + public List> threeSum(int[] nums) { + Map numsMap = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + numsMap.putIfAbsent(nums[i], i); + } + + List> result = new ArrayList<>(); + for (Integer key : numsMap.keySet()) { + int newTarget = TARGET - key; + int i = numsMap.get(key) + 1; + while (i < nums.length) { + int lastValue = newTarget - nums[i]; + if (numsMap.containsKey(lastValue) && numsMap.get(lastValue) != i && lastValue != key) { + result.add(new ArrayList<>(Arrays.asList(key, nums[i], lastValue))); + break; + } + i++; + } + } + + + return result; + } +} diff --git a/src/dami/leetcode/medium/Top_K_Frequent_Elements_347.java b/src/dami/leetcode/medium/Top_K_Frequent_Elements_347.java new file mode 100644 index 0000000..50da685 --- /dev/null +++ b/src/dami/leetcode/medium/Top_K_Frequent_Elements_347.java @@ -0,0 +1,46 @@ +package dami.leetcode.medium; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.PriorityQueue; + +// https://leetcode.com/problems/top-k-frequent-elements/ +public class Top_K_Frequent_Elements_347 { + public int[] topKFrequent(int[] nums, int k) { + Map numMap = new HashMap<>(); + for (int num : nums) { + numMap.put(num, numMap.getOrDefault(num, 0) + 1); + } + + return numMap.keySet().stream() + .sorted((key1, key2) -> numMap.get(key2).compareTo(numMap.get(key1))) + .limit(k) + .mapToInt(num -> num) + .toArray(); + } +} + +/* +// PriorityQueue 사용한 방법 +public int[] topKFrequent(int[] nums, int k) { + + Map map = new HashMap(); + for(int i: nums) + map.put(i, map.getOrDefault(i, 0) + 1); + + PriorityQueue queue = new PriorityQueue(k, (n1, n2)->map.get(n1)-map.get(n2)); + for(Map.Entry entry : map.entrySet()){ + queue.add(entry.getKey()); + if(queue.size() > k) + queue.poll(); + } + int[] res = new int[k]; + int i = 0; + while(queue.size() > 0) + res[i++] = queue.poll(); + return res; + +} + +*/ diff --git a/src/dami/leetcode/medium/review/Binary_Tree_Inorder_94.java b/src/dami/leetcode/medium/review/Binary_Tree_Inorder_94.java new file mode 100644 index 0000000..df012f1 --- /dev/null +++ b/src/dami/leetcode/medium/review/Binary_Tree_Inorder_94.java @@ -0,0 +1,47 @@ +package dami.leetcode.medium.review; + +import dami.leetcode.common.TreeNode; + +import java.util.*; + +// https://leetcode.com/problems/binary-tree-inorder-traversal/ +public class Binary_Tree_Inorder_94 { + public List inorderTraversal(TreeNode root) { + root = new TreeNode(4, new TreeNode(2, new TreeNode(1), new TreeNode(3)), new TreeNode(5, new TreeNode(7), new TreeNode(8))); + List result = new ArrayList<>(); + + // 1. 순환 방법 + recursive(root, result); + // 2. 반복 방법 + iteration(root, result); + + return result; + } + + private void recursive(TreeNode node, List result) { + if (null == node) { + return; + } + recursive(node.left, result); + result.add(node.val); + recursive(node.right, result); + } + + private void iteration(TreeNode node, List result) { + if (null == node) { + return; + } + Stack stack = new Stack<>(); + TreeNode current = node; + while (null != current || !stack.isEmpty()) { + while (null != current) { + stack.push(current); + current = current.left; + } + current = stack.pop(); + result.add(current.val); + current = current.right; + } + } + +} diff --git a/src/dami/leetcode/medium/review/Counting_Bits_338.java b/src/dami/leetcode/medium/review/Counting_Bits_338.java new file mode 100644 index 0000000..bb526f9 --- /dev/null +++ b/src/dami/leetcode/medium/review/Counting_Bits_338.java @@ -0,0 +1,37 @@ +package dami.leetcode.medium.review; + +// https://leetcode.com/problems/counting-bits/ +public class Counting_Bits_338 { + public int[] countBits(int num) { + return solution2(num); + } + + // 방법 1. O(n^2) + private int[] solution1(int num) { + int[] result = new int[num + 1]; + for (int i = num; i >= 0; i--) { + int sum = 0; + int n = i; + while (n >= 1) { + sum += n % 2; + n = n / 2; + } + result[i] = sum; + } + return result; + } + + // 방법 2. 비트연산자 사용 O(n) + private int[] solution2(int num) { + int[] result = new int[num + 1]; + for (int i = 1; i <= num; i++) { + // " f[i >> 1] " is equivalent to " f[i / 2] " + // => 짝수는 비트연산으로 한 칸 밀어도(2로 나누면) 무조건 1이 한 개 + // " i & 1 " is equivalent to " i % 2 " + // => 홀수는 비트연산으로 한 칸 밀면 1 한 개가 없어짐. + // 예를 들어 5의 2진수는 101이되고 " 101 & 1 " 하면 비트연산으로 없어진 1 추가 가능 + result[i] = result[i >> 1] + (i & 1); + } + return result; + } +} diff --git a/src/dami/leetcode/medium/review/Longest_Palindromic_Substring_5.java b/src/dami/leetcode/medium/review/Longest_Palindromic_Substring_5.java new file mode 100644 index 0000000..e94fa53 --- /dev/null +++ b/src/dami/leetcode/medium/review/Longest_Palindromic_Substring_5.java @@ -0,0 +1,66 @@ +package dami.leetcode.medium.review; + +// https://leetcode.com/problems/longest-palindromic-substring/ +// 문자열 길이만큼 반복 +// 현재 위치 기준으로 왼쪽 오른쪽으로 한자리씩 뻗어나가며 두 char가 같은지 비교해주는 방법 +public class Longest_Palindromic_Substring_5 { + public String longestPalindrome(String s) { + String result = ""; + for (int i = 0; i < s.length(); i++) { + String odd = compareLeftRight(s, i, i); + String even = compareLeftRight(s, i, i + 1); + if (odd.length() > result.length()) { + result = odd; + } + if (even.length() > result.length()) { + result = even; + } + } + + return result; + } + + public String compareLeftRight(String s, int i, int j) { + for (; i <= 0 && j < s.length(); i--, j++) { + if (s.charAt(i) != s.charAt(j)) { + break; + } + } + return s.substring(i + 1, j); + } + + + // 문자열 길이만큼 맨 앞 인덱스와 같은 마지막 인덱스 찾아서 안으로 들어가며 비교해주는 방법 + // aaca / acaa 인 경우 등 실패 + public String longestPalindrome_실패(String s) { + String result = String.valueOf(s.charAt(0)); + for (int i = 0; i < s.length(); i++) { + + char first = s.charAt(i); + int lastIndex = s.lastIndexOf(first); + + if (lastIndex + 1 - i <= result.length()) { + continue; + } + + if (lastIndex == i || lastIndex == -1) { + continue; + } + + if (isPalindrome(s, i, lastIndex)) { + result = s.substring(i, lastIndex + 1); + } + } + + return result; + } + + private boolean isPalindrome(String s, int currentIndex, int lastIndex) { + for (int j = currentIndex + 1; j < (lastIndex - currentIndex + 1) / 2 + currentIndex; j++) { + if (s.charAt(j) != s.charAt(lastIndex - j + currentIndex)) { + return false; + } + } + return true; + } +} diff --git a/src/dami/leetcode/medium/review/Queue_Reconstruction_406.java b/src/dami/leetcode/medium/review/Queue_Reconstruction_406.java new file mode 100644 index 0000000..2fdd7cb --- /dev/null +++ b/src/dami/leetcode/medium/review/Queue_Reconstruction_406.java @@ -0,0 +1,24 @@ +package dami.leetcode.medium.review; + +import java.util.*; + +// https://leetcode.com/problems/queue-reconstruction-by-height/ +public class Queue_Reconstruction_406 { + public int[][] reconstructQueue(int[][] people) { + LinkedList reconstructed = new LinkedList<>(); + + // 두 height가 같으면 [7, 0] [7, 1] + // [][1] 오름차순 정렬 + // 두 height가 다르면 [4, 4] [5, 0] + // height([][0]) 내림차순 정렬 + Arrays.sort(people, (p1, p2) -> p1[0] == p2[0] ? p1[1] - p2[1] : p2[0] - p1[0]); + + // 정렬한 상태에서 [][1] 위치에 넣어주기만 하면 reconstructed + for (int[] person : people) { + reconstructed.add(person[1], person); + } + + return reconstructed.toArray(new int[people.length][]); + } + +} diff --git a/src/dami/programmers/Programmers.java b/src/dami/programmers/Programmers.java new file mode 100644 index 0000000..885230e --- /dev/null +++ b/src/dami/programmers/Programmers.java @@ -0,0 +1,67 @@ +package dami.programmers; + +import dami.programmers.level1.추억_점수; +import dami.programmers.level2.요격_시스템; + +import java.util.Arrays; + +public class Programmers { + public void solutions() { + ////////////////////////////////////////////////////////////////////////////// + /* level1 */ + //new 정수_삼각형().solution(new int[][] {{7}, {3, 8}, {8, 1, 0}, {2, 7, 4, 4}, {4, 5, 2, 6, 5}}); +// int[] result = new 추억_점수().solution(new String[]{"may", "kein", "kain", "radi"}, +// new int[]{5, 10, 1, 3}, +// new String[][]{{"may", "kein", "kain", "radi"}, {"may", "kein", "brin", "deny"}, {"kon", "kain", "may", "coni"}}); + int result = new 요격_시스템().solution(new int[][]{{0, 4}, {0, 1}, {2, 3}}); + System.out.println(result); + ////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////// + /* level2 */ + //new 멀쩡한_사각형().solution(100000000, 100000001); + //new 일이사_나라의_숫자().solution(20); + //new 기능개발().solution(new int[] {93, 30, 55}, new int[] {1, 30, 5}); + //new 카카오프렌즈_컬러링북().solution(6, 4, new int[][] {{1, 1, 1, 0}, {1, 2, 2, 0}, {1, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 3}, {0, 0, 0, 3}}); + //new 문자열_압축().solution("abcabcdede"); + //new 삼각_달팽이().solution(4); + //new 조이스틱().solution("JEROEN"); + //new 소수찾기().solution("1234"); + //new 타겟_넘버().solution(new int[] {2, 3, 5, 7, 9}, 8); + //new 가장_큰_정사각형_찾기().solution(new int[][]{{0,1,1,1},{1,1,1,1},{1,1,1,1},{0,0,1,0}}); + //new 땅따먹기().solution(new int[][]{{1, 2, 3, 5}, {5, 6, 7, 100}, {4, 3, 2, 1}}); + //new 폰켓몬().solution(new int[] {3, 3, 3, 2, 2, 4}); + //new 튜플().solution("{{4,2,3},{3},{2,3,4,1},{2,3}}"); + //new 수식_최대화().solution("100-200*300-500+20"); + //new 짝지어_제거하기().solution("cdcd"); + //new 더_맵게().solution(new int[] {1, 2, 3, 9, 10, 12}, 7); + //new 이진_변환_반복하기().solution("01110"); + //new 압축().solution("ABABABABABABABAB"); + //new 최솟값_만들기().solution(new int[] {1, 4, 2}, new int[] {5, 4, 4}); + //new 방금그곡().solution("ABCDEFG", new String[]{"13:50,14:05,HELLO,CDEFGAB", "13:00,13:30,WORLD,CDEFGAB"})); + //new 오픈채팅방().solution(new String[]{"Enter uid1234 Muzi", "Enter uid4567 Prodo", "Leave uid1234", "Enter uid1234 Prodo", "Change uid4567 Ryan"}); + //new 뉴스_클러스터링().solution("FRANCE", "french"); + //new 프렌즈4블록().solution(4, 5, new String[]{"CCBDE", "AAADE", "AAABF", "CCBBF"}); + //new 프렌즈4블록().solution(6, 6, new String[]{"AABBEE", "AAAEEE", "VAAEEV", "AABBEE", "AACCEE", "VVCCEE"}); + //new 캐시().solution(3, new String[]{"Jeju", "Pangyo", "Seoul", "NewYork", "LA", "Jeju", "Pangyo", "Seoul", "NewYork", "LA"}); + //new 캐시().solution(2, new String[]{"Jeju", "Pangyo", "NewYork", "newyork"}); + //new 파일명_정렬().solution(new String[]{"img00000", "a099", "img0.png", "img1.png", "IMG01.GIF", "img2.JPG"}); + //new 파일명_정렬().solution(new String[]{"img000045123.", "img.1-.1.1.b.png", "img2", "IMG02"}); + //new 점프와_순간_이동().solution(1); + //new 예상_대진표().solution(16, 8, 9); + //new 후보키().solution(new String[][] {}); + ////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////// + /* level3 */ + //new 정수_삼각형().solution(new int[][] {{7}, {3, 8}, {8, 1, 0}, {2, 7, 4, 4}, {4, 5, 2, 6, 5}}); + //new 등굣길().solution(1, 3, new int[][] {{1, 1}}); + //new 자물쇠와_열쇠().solution(new int[][]{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}, new int[][]{{1, 1, 1}, {1, 1, 0}, {1, 0, 1}}); + //new 셔틀버스().solution(3, 60, 2, new String[]{"09:00", "09:05", "09:05", "09:05", "09:05", "09:05", "11:00"}); + //new 셔틀버스().solution(2, 10, 2, new String[]{"09:10", "09:09", "08:00"}); + //new 셔틀버스().solution(1,1,1, new String[]{"23:59"}); + //new 셔틀버스().solution(1,1,2, new String[]{"23:59"}); + //new 셔틀버스().solution(1,1,5, new String[]{"08:00", "08:01", "08:02", "08:03"}); + ////////////////////////////////////////////////////////////////////////////// + } +} diff --git "a/src/dami/programmers/level1/\354\266\224\354\226\265_\354\240\220\354\210\230.java" "b/src/dami/programmers/level1/\354\266\224\354\226\265_\354\240\220\354\210\230.java" new file mode 100644 index 0000000..3e1514e --- /dev/null +++ "b/src/dami/programmers/level1/\354\266\224\354\226\265_\354\240\220\354\210\230.java" @@ -0,0 +1,27 @@ +package dami.programmers.level1; + +import java.util.HashMap; +import java.util.Map; + +public class 추억_점수 { + + public int[] solution(String[] name, int[] yearning, String[][] photo) { + int[] answer = new int[photo.length]; + + Map yearningRank = new HashMap<>(); + for (int i = 0; i < name.length; i++) { + yearningRank.put(name[i], yearning[i]); + } + + int i = 0; + for (String[] currentPhoto : photo) { + int sum = 0; + for (String personName : currentPhoto) { + sum += yearningRank.getOrDefault(personName, 0); + } + answer[i++] = sum; + } + + return answer; + } +} diff --git "a/src/dami/programmers/level2/JadenCase_\353\254\270\354\236\220\354\227\264_\353\247\214\353\223\244\352\270\260.java" "b/src/dami/programmers/level2/JadenCase_\353\254\270\354\236\220\354\227\264_\353\247\214\353\223\244\352\270\260.java" new file mode 100644 index 0000000..40e565c --- /dev/null +++ "b/src/dami/programmers/level2/JadenCase_\353\254\270\354\236\220\354\227\264_\353\247\214\353\223\244\352\270\260.java" @@ -0,0 +1,59 @@ +package dami.programmers.level2; + +import java.util.StringTokenizer; + +public class JadenCase_문자열_만들기 { + public String solution() { + StringBuilder answer = new StringBuilder(); + + String s = " for 3the last week "; + String[] words = s.toLowerCase().split("\\s"); + for (String word : words) { + if (word.isEmpty()) { + answer.append(" "); + continue; + } + + answer.append(word.substring(0, 1).toUpperCase()) + .append(word.substring(1)) + .append(" "); + } + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == ' '); + } + + StringTokenizer tokenizer = new StringTokenizer(s); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + String jadenToken = token.substring(0,1).toUpperCase() + token.substring(1); + } + + System.out.println(answer.toString()); + return answer.substring(0, answer.length() - 1); + } + + public String solution2(String s) { + StringBuilder answer = new StringBuilder(s.toLowerCase()); + boolean isEmpty = true; + for (int i = 0; i < s.length(); i++) { + char currentChar = s.charAt(i); + if (currentChar == ' ') { + isEmpty = true; + continue; + } + + if (isEmpty) { + answer.replace(i, i + 1, String.valueOf(currentChar).toUpperCase()); + isEmpty = false; + } + } + + System.out.println(answer.toString()); + return answer.toString(); + } + + public static void main(String[] args) { + new JadenCase_문자열_만들기().solution2(""); + } +} diff --git "a/src/dami/programmers/level2/review/\354\235\274\354\235\264\354\202\254_\353\202\230\353\235\274\354\235\230_\354\210\253\354\236\220.java" "b/src/dami/programmers/level2/review/\354\235\274\354\235\264\354\202\254_\353\202\230\353\235\274\354\235\230_\354\210\253\354\236\220.java" new file mode 100644 index 0000000..0278815 --- /dev/null +++ "b/src/dami/programmers/level2/review/\354\235\274\354\235\264\354\202\254_\353\202\230\353\235\274\354\235\230_\354\210\253\354\236\220.java" @@ -0,0 +1,48 @@ +package dami.programmers.level2.review; + +// ** 이해 제대로 못함 +// 나머지 0일 때 왜 몫에서 1 빼야 하는건지? 나머지, 124나라 값이랑 몫 규칙순서 맞출라고?? +/** + * + * 10진법 목(/3) 나머지(%3) 124나라 + * ------------------------------------------------ + * 1 0 1 1 + * 2 0 2 2 + * 3 1 0 4 + * 4 1 1 11 + * 5 1 2 12 + * 6 2 0 14 + * 7 2 1 21 + * 8 2 2 22 + * 9 3 0 24 + * 10 3 1 41 + * + */ +public class 일이사_나라의_숫자 { + public String solution(int n) { + StringBuilder answer = new StringBuilder(); + + int remain = 0; + while (n != 0) { + remain = n % 3; + n = (n - 1) / 3; + + answer.append("412".charAt(remain)); + } + + return answer.reverse().toString(); + } + + /* // 다른 풀이 + public String solution(int n) { + String[] num = {"4","1","2"}; + String answer = ""; + + while(n > 0){ + answer = num[n % 3] + answer; + n = (n - 1) / 3; + } + return answer; + } + */ +} diff --git "a/src/dami/programmers/level2/review/\354\241\260\354\235\264\354\212\244\355\213\261.java" "b/src/dami/programmers/level2/review/\354\241\260\354\235\264\354\212\244\355\213\261.java" new file mode 100644 index 0000000..65819cb --- /dev/null +++ "b/src/dami/programmers/level2/review/\354\241\260\354\235\264\354\212\244\355\213\261.java" @@ -0,0 +1,58 @@ +package dami.programmers.level2.review; + +import java.util.Arrays; +import java.util.stream.IntStream; + +// 웩 +// 1. 문자열 길이만큼 반복 돌리면서 상하 최소 이동값 전체 구하기 +// 2. 좌우 최소 이동값 구하기 +public class 조이스틱 { + public int solution(String name) { + char[] checkedName = name.toCharArray(); + return moveUpDown(checkedName) + moveLeftRight(checkedName); + } + + private int moveUpDown(char[] name) { + int count = 0; + for (char alphabet : name) { + count += Math.min(alphabet - 'A', 1 + 'Z' - alphabet); + } + return count; + } + + private int moveLeftRight(char[] name) { + char[] leftName = Arrays.copyOf(name, name.length); + char[] rightName = Arrays.copyOf(name, name.length); + leftName[0] = 'A'; + rightName[0] = 'A'; + + int moveCount = 0; + int leftIndex = 1, leftCount = 1; + int rightIndex = name.length - 1, rightCount = 1; + while (!isAllA(rightName)) { + while (leftName[leftIndex] == 'A') { + leftCount++; + leftIndex = leftIndex % name.length; + } + leftName[leftIndex] = 'A'; + while (rightName[rightIndex] == 'A') { + rightCount++; + rightIndex = (rightIndex == 0 ? name.length - 1 : rightIndex) % name.length; + } + rightName[rightIndex] = 'A'; + + moveCount += Math.min(leftCount, rightCount); + + leftIndex++; + rightIndex--; + } + return moveCount; + } + + private boolean isAllA(char[] name) { + return IntStream.range(0, name.length) + .mapToObj(i -> name[i]) + .allMatch(n -> n == 'A'); + } + +} diff --git "a/src/dami/programmers/level2/review/\355\224\204\353\240\214\354\246\2104\353\270\224\353\241\235.java" "b/src/dami/programmers/level2/review/\355\224\204\353\240\214\354\246\2104\353\270\224\353\241\235.java" new file mode 100644 index 0000000..2879d59 --- /dev/null +++ "b/src/dami/programmers/level2/review/\355\224\204\353\240\214\354\246\2104\353\270\224\353\241\235.java" @@ -0,0 +1,84 @@ +package dami.programmers.level2.review; + +// https://programmers.co.kr/learn/courses/30/lessons/17679 +public class 프렌즈4블록 { + private static final char VISITED = '-'; + + public int solution(int m, int n, String[] board) { + char[][] blocks = new char[m][n]; + for (int i = 0; i < m; i++) { + blocks[i] = board[i].toCharArray(); + } + + int sum = 0; + while (true) { + int removed = find2x2Blocks(blocks, m, n); + if (removed == 0) { + break; + } + sum += removed; + + // 끌어내리기 + dropBlocks(blocks, m, n); + } + + return sum; + } + + private int find2x2Blocks(char[][] board, int m, int n) { + boolean[][] visited = new boolean[m][n]; + for (int i = 0; i < m - 1; i++) { + for (int j = 0; j < n - 1; j++) { + if (is2x2(board, i, j)) { + visited[i][j] = true; + visited[i][j + 1] = true; + visited[i + 1][j] = true; + visited[i + 1][j + 1] = true; + } + } + } + + int count = 0; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (visited[i][j]) { + board[i][j] = '-'; + count++; + } + } + } + + return count; + } + + private boolean is2x2(char[][] board, int i, int j) { + char current = board[i][j]; + return current != '-' + && current == board[i][j + 1] + && current == board[i + 1][j] + && current == board[i + 1][j + 1] + && i < board.length - 1 + && j < board[i].length - 1; + } + + // C C B D E + // - - - D E + // - - - B F + // C C B B F + // 가장 아랫줄부터 - 인 경우 찾아서 찾은 위치부터 위로 올라가면서 - 아닌 경우랑 swap + private void dropBlocks(char[][] board, int m, int n) { + for (int i = m - 1; i > 0; i--) { + for (int j = 0; j < n; j++) { + if (board[i][j] == VISITED) { + for (int k = i - 1; k >= 0; k--) { + if (board[k][j] != VISITED) { + board[i][j] = board[k][j]; + board[k][j] = VISITED; + break; + } + } + } + } + } + } +} diff --git "a/src/dami/programmers/level2/\352\260\200\354\236\245_\355\201\260_\354\240\225\354\202\254\352\260\201\355\230\225_\354\260\276\352\270\260.java" "b/src/dami/programmers/level2/\352\260\200\354\236\245_\355\201\260_\354\240\225\354\202\254\352\260\201\355\230\225_\354\260\276\352\270\260.java" new file mode 100644 index 0000000..65f7f78 --- /dev/null +++ "b/src/dami/programmers/level2/\352\260\200\354\236\245_\355\201\260_\354\240\225\354\202\254\352\260\201\355\230\225_\354\260\276\352\270\260.java" @@ -0,0 +1,24 @@ +package dami.programmers.level2; + +import java.util.Arrays; + +// https://programmers.co.kr/learn/courses/30/lessons/12905 +public class 가장_큰_정사각형_찾기 { + public int solution(int [][]board) { + int max = Arrays.stream(board[0]).anyMatch(value -> value == 1) ? 1 : 0; + for (int i = 1; i < board.length; i++) { + for (int j = 1; j < board[i].length; j++) { + if (board[i][j] == 0) { + continue; + } + board[i][j] += minimumOfThree(board[i-1][j-1], board[i][j-1], board[i-1][j]); + max = Math.max(max, board[i][j]); + } + } + return max * max; + } + + private int minimumOfThree(int one, int two, int three) { + return Math.min(one, Math.min(two, three)); + } +} diff --git "a/src/dami/programmers/level2/\352\270\260\353\212\245\352\260\234\353\260\234.java" "b/src/dami/programmers/level2/\352\270\260\353\212\245\352\260\234\353\260\234.java" new file mode 100644 index 0000000..3742fde --- /dev/null +++ "b/src/dami/programmers/level2/\352\270\260\353\212\245\352\260\234\353\260\234.java" @@ -0,0 +1,35 @@ +package dami.programmers.level2; + +import java.util.ArrayList; +import java.util.List; + +// 1. 배포 일 수 배열 구하기 +// 2. 배포 일 수 배열 크기만큼 반복 +// - 다음 값이 현재 값보다 작으면 count++ +// - 다음 값이 현재 값보다 크면 턴 넘기기 +public class 기능개발 { + public int[] solution(int[] progresses, int[] speeds) { + + int[] deploys = new int[progresses.length]; + for (int i = 0; i < progresses.length; i++) { + int maybeDeploy = 100 - progresses[i]; + if (speeds[i] == 1) { + deploys[i] = maybeDeploy; + continue; + } + deploys[i] = maybeDeploy / speeds[i] + (maybeDeploy % speeds[i] == 0 ? 0 : 1); + } + + int i = 1; + int current = 0; + List answer = new ArrayList<>(); + for (; i < deploys.length; i++) { + if (deploys[current] < deploys[i]) { + answer.add(i - current); + current = i; + } + } + answer.add(i - current); + return answer.stream().mapToInt(a -> a).toArray(); + } +} diff --git "a/src/dami/programmers/level2/\353\211\264\354\212\244_\355\201\264\353\237\254\354\212\244\355\204\260\353\247\201.java" "b/src/dami/programmers/level2/\353\211\264\354\212\244_\355\201\264\353\237\254\354\212\244\355\204\260\353\247\201.java" new file mode 100644 index 0000000..922a931 --- /dev/null +++ "b/src/dami/programmers/level2/\353\211\264\354\212\244_\355\201\264\353\237\254\354\212\244\355\204\260\353\247\201.java" @@ -0,0 +1,59 @@ +package dami.programmers.level2; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +// https://programmers.co.kr/learn/courses/30/lessons/17677 + +// 1. 주어진 두 문자열 각각 2글자씩 끊고, 소문자로 바꾸고 알파벳 외 문자는 버려서 Map에 저장 +// 2. 두 맵에 공통으로 들은 key 중 작은 value의 합 = 교집합 개수 +// 3. 두 맵에 공통으로 들은 key 중 큰 value의 합 + 공통 아닌 key의 value의 합 = 합집합 개수 +public class 뉴스_클러스터링 { + private static final Pattern ALPHABET = Pattern.compile("[a-z]*"); + + public int solution(String str1, String str2) { + Map str1Map = divideString(str1); + Map str2Map = divideString(str2); + + int inter = getIntersectionCount(str1Map, str2Map); + int union = getUnionCount(str1Map, str2Map); + + return union == 0 ? 65536 : (int)((double) inter / union * 65536); + } + + private Map divideString(String str) { + Map map = new HashMap<>(); + for (int i = 0; i < str.length() - 1; i++) { + String divided = str.substring(i, i + 2).toLowerCase(); + if (ALPHABET.matcher(divided).matches()) { + map.put(divided, map.getOrDefault(divided, 0) + 1); + } + } + return map; + } + + private int getIntersectionCount(Map map1, Map map2) { + return map1.keySet().stream() + .filter(map2::containsKey) + .mapToInt(key -> Math.min(map1.get(key), map2.get(key))) + .sum(); + } + + private int getUnionCount(Map map1, Map map2) { + int same = map1.keySet().stream() + .filter(map2::containsKey) + .mapToInt(key -> Math.max(map1.get(key), map2.get(key))) + .sum(); + int diff = map1.keySet().stream() + .filter(key -> !map2.containsKey(key)) + .mapToInt(map1::get) + .sum() + + + map2.keySet().stream() + .filter(key -> !map1.containsKey(key)) + .mapToInt(map2::get) + .sum(); + return same + diff; + } +} diff --git "a/src/dami/programmers/level2/\353\213\244\354\235\214_\355\201\260_\354\210\253\354\236\220.java" "b/src/dami/programmers/level2/\353\213\244\354\235\214_\355\201\260_\354\210\253\354\236\220.java" new file mode 100644 index 0000000..b9df102 --- /dev/null +++ "b/src/dami/programmers/level2/\353\213\244\354\235\214_\355\201\260_\354\210\253\354\236\220.java" @@ -0,0 +1,72 @@ +package dami.programmers.level2; + +public class 다음_큰_숫자 { + public int solution_timeout(int n) { + int answer = 0; + String binary = Integer.toBinaryString(n); + int oneCount = binary.replaceAll("0", "").length(); + + for (int i = n + 1; i < Integer.MAX_VALUE; i++) { + int nextNumberOneCount = 0; + char[] binaryChars = Integer.toBinaryString(i).toCharArray(); + for (char binaryChar : binaryChars) { + if (binaryChar == '1') { + nextNumberOneCount++; + } + } + if (nextNumberOneCount == oneCount) { + return i; + } + } + + return answer; + } + + public int solution(int n) { + int oneCount = getOneCount(n); + + for (int answer = n + 1; answer < Integer.MAX_VALUE; answer++) { + if (getOneCount(answer) == oneCount) { + return answer; + } + } + return 0; + } + + private int getOneCount(int num) { + int oneCount = 0; + int o = num; + while (o > 0) { + if (o % 2 == 1) { + oneCount++; + } + o = o / 2; + } + + return oneCount; + } + + + + public int solution_fail(int n) { + int answer = 0; + + int[] oneCounts = new int[n]; + for (int i = 1; i <= n; i++) { + oneCounts[i - 1] = Integer.toBinaryString(i).replaceAll("0", "").length(); + } + + int oneCount = oneCounts[n]; + for (int i = n / 2; i < oneCounts.length; i++) { + if (oneCount == oneCounts[i]) { + return i * 2 - 1; + } + } + return answer; + } + + public static void main(String[] args) { + System.out.println(new 다음_큰_숫자().solution(15)); + //new 다음_큰_숫자().solution_fail(73); + } +} diff --git "a/src/dami/programmers/level2/\353\215\224_\353\247\265\352\262\214.java" "b/src/dami/programmers/level2/\353\215\224_\353\247\265\352\262\214.java" new file mode 100644 index 0000000..5b330fc --- /dev/null +++ "b/src/dami/programmers/level2/\353\215\224_\353\247\265\352\262\214.java" @@ -0,0 +1,40 @@ +package dami.programmers.level2; + +import java.util.PriorityQueue; + +// https://programmers.co.kr/learn/courses/30/lessons/42626 +// 처음엔 앞에서부터 합치도록 구현함 +// 테스트 케이스 실패 +// 반례 케이스 : [1, 1, 1, 1, 3] +// 1회 합치면 [3, 1, 1, 3]이 되고, 가장 작은 + 그 다음 작은 수를 찾아야 하는데 정렬이 되어있지 않으니 앞에서부터 3, 1로 합치게 됨 + +// 우선순위 큐 사용하도록 수정 +// 큐의 각 값에 우선순위가 정해져있으며 힙을 이용해 구현 +// 힙 : 완전 이진 트리의 일종으로 **여러 값 중 최대/최솟값을 빨리 찾기** 위한 자료구조 (중복 허용) +// 최소 힙은 우선순위가 오름차순 정렬, 최대 힙은 우선순위가 내림차순 정렬 +// 힙 자료구조 : https://gmlwjd9405.github.io/2018/05/10/data-structure-heap.html +// 자바의 PriorityQueue 사용 : https://coding-factory.tistory.com/603 + +public class 더_맵게 { + public int solution(int[] scoville, int K) { + PriorityQueue scovilleQ = new PriorityQueue<>(); + for (int scov : scoville) { + scovilleQ.add(scov); + } + + int count = 0; + int min; + while (scovilleQ.size() > 1) { + min = scovilleQ.poll(); + if (min >= K) { + break; + } + + min += scovilleQ.poll() * 2; + scovilleQ.add(min); + count++; + } + + return scovilleQ.poll() >= K ? count : -1; + } +} diff --git "a/src/dami/programmers/level2/\353\221\220_\354\233\220_\354\202\254\354\235\264\354\235\230_\354\240\225\354\210\230\354\214\215.java" "b/src/dami/programmers/level2/\353\221\220_\354\233\220_\354\202\254\354\235\264\354\235\230_\354\240\225\354\210\230\354\214\215.java" new file mode 100644 index 0000000..2ae3a67 --- /dev/null +++ "b/src/dami/programmers/level2/\353\221\220_\354\233\220_\354\202\254\354\235\264\354\235\230_\354\240\225\354\210\230\354\214\215.java" @@ -0,0 +1,10 @@ +package dami.programmers.level2; + +public class 두_원_사이의_정수쌍 { + + public long solution(int r1, int r2) { + int bigDiameter = Math.max(r1, r2) * 2; + int smallDiameter = Math.min(r1, r2) * 2; + return (long) (Math.pow(bigDiameter - 1, 2) - Math.pow(smallDiameter - 1, 2) + 4); + } +} diff --git "a/src/dami/programmers/level2/\353\225\205\353\224\260\353\250\271\352\270\260.java" "b/src/dami/programmers/level2/\353\225\205\353\224\260\353\250\271\352\270\260.java" new file mode 100644 index 0000000..dccd579 --- /dev/null +++ "b/src/dami/programmers/level2/\353\225\205\353\224\260\353\250\271\352\270\260.java" @@ -0,0 +1,40 @@ +package dami.programmers.level2; + +import java.util.Arrays; + +// https://programmers.co.kr/learn/courses/30/lessons/12913 + +// 처음에는 단순히 아래로 내려가면서 최댓값을 sum 하는 반복문으로 풀었지만 +// 1 2 3 5 +// 5 6 7 100 +// 4 3 2 1 +// 위와 같은 예시일 경우 오답 + +// 1. 두 번째 행부터 시작 +// 2. 각 인덱스마다 본인 인덱스 제외한 윗 행 값과 더한 값 중 최댓값으로 갱신 +// 3. 마지막 행까지 반복 +// 4. 마지막 행의 최댓값 반환 +public class 땅따먹기 { + public int solution(int[][] land) { + for (int i = 1; i < land.length; i++) { + for (int j = 0; j < land[i].length; j++) { + land[i][j] = findMaxSum(land[i-1], land[i][j], j); + } + } + + return Arrays.stream(land[land.length - 1]) + .max() + .orElse(0); + } + + private int findMaxSum(int[] prevLine, int currentValue, int exceptIndex) { + int max = 0; + for (int i = 0; i < prevLine.length; i++) { + if (i == exceptIndex) { + continue; + } + max = Math.max(max, currentValue + prevLine[i]); + } + return max; + } +} diff --git "a/src/dami/programmers/level2/\353\251\200\354\251\241\355\225\234_\354\202\254\352\260\201\355\230\225.java" "b/src/dami/programmers/level2/\353\251\200\354\251\241\355\225\234_\354\202\254\352\260\201\355\230\225.java" new file mode 100644 index 0000000..51d9ae4 --- /dev/null +++ "b/src/dami/programmers/level2/\353\251\200\354\251\241\355\225\234_\354\202\254\352\260\201\355\230\225.java" @@ -0,0 +1,48 @@ +package dami.programmers.level2; + +// 1. 두 수의 최대공약수 구하기 +// 2. 두 수에 최대공약수로 나눠서 나온 수로 만들어진 작은 직사각형의 대각선 커팅 시 잘린 사각형 개수 구하기 +// - 최대 공약수가 1인 두 수로 만들어진 직사각형의 잘린 사각형 개수 = 가로 + 세로 - 1 +// 3. 잘린 사각형 개수 * 최대공약수 = 처음에 주어진 두 수로 만들어진 직사각형의 전체 잘린 사각형 개수 +// ** 계산 시 형변환 주의 ** + +// - 수식 정리 +// 가로 W, 세로 H, W와 H의 최대공약수 gcd +// gcd로 나눈 가로 w, 세로 h (w, h의 최대공약수는 1) +// 멀쩡한 사각형 계산식 : W * H - (w + h - 1) * gcd +// == W * H - (W + H - gcd) + +// #### 최대공약수 구하는 방법 +// - 유클리드 호제법 활용 +// - 유클리드 호제법은 mod 연산으로 사용 가능 +// ** mod 연산? : 두 값을 나눈 나머지를 구하는 연산 + +/** + * ex. 1112와 695의 최대공약수 구하기 + * 1112 mod 695 = 417 + * 695 mod 417 = 278 + * 417 mod 278 = 139 + * 278 mod 139 = 0 + * ==> 139가 1112와 695의 최대공약수 + */ +public class 멀쩡한_사각형 { + public long solution(int w, int h) { + return ((long)w * h) - (w + h - calculateGcd(w, h)); + } + + private int calculateGcd(int w, int h) { + if (h > w) { + int temp = w; + w = h; + h = temp; + } + + int remainder; + while (h != 0) { + remainder = w % h; + w = h; + h = remainder; + } + return w; + } +} diff --git "a/src/dami/programmers/level2/\353\254\270\354\236\220\354\227\264_\354\225\225\354\266\225.java" "b/src/dami/programmers/level2/\353\254\270\354\236\220\354\227\264_\354\225\225\354\266\225.java" new file mode 100644 index 0000000..bbca03c --- /dev/null +++ "b/src/dami/programmers/level2/\353\254\270\354\236\220\354\227\264_\354\225\225\354\266\225.java" @@ -0,0 +1,66 @@ +package dami.programmers.level2; + +import java.util.Stack; + +// 1. 문자열 길이만큼 반복 +// - 문자열 맨 앞 자르기 +// - 인덱스(==자를 문자열 개수)가 잘린 문자열 길이 초과하면 남은 문자열 뒤에 그대로 붙이기 +// - 자른 문자열 스택에 넣고 같은지 다른지 비교 +// - 같으면 스택에 추가 / 다르면 압축 문자열 길이 += +// 2. 문자열 인덱스만큼 모두 자를 때까지 반복했는데 스택에 남은 값 있으면 압축 문자열 길이 += +// 3. 압축 문자열 길이 최소값 비교해서 return +public class 문자열_압축 { + public int solution(String s) { + int answer = Integer.MAX_VALUE; + + if (s.length() == 1) { + return 1; + } + + Stack stringStack = new Stack<>(); + for (int i = 1; i <= s.length(); i++) { + StringBuilder originString = new StringBuilder(s); + int compressedLength = 0; + + String substring = substringAndDelete(originString, i); + stringStack.push(substring); + + while (originString.length() != 0) { + if (i > originString.length()) { + compressedLength += originString.length(); + break; + } + + substring = substringAndDelete(originString, i); + if (stringStack.peek().equals(substring)) { + stringStack.push(substring); + continue; + } + + compressedLength += compressString(stringStack); + stringStack.removeAllElements(); + stringStack.push(substring); + } + + if (!stringStack.isEmpty()) { + compressedLength += compressString(stringStack); + stringStack.removeAllElements(); + } + + answer = Math.min(answer, compressedLength); + } + + return answer; + } + + private String substringAndDelete(StringBuilder stringBuilder, int index) { + String substring = stringBuilder.substring(0, index); + stringBuilder.delete(0, index); + return substring; + } + + private int compressString(Stack stringStack) { + return ((stringStack.size() > 1 ? stringStack.size() : "") + stringStack.pop()).length(); + } + +} diff --git "a/src/dami/programmers/level2/\353\260\251\352\270\210\352\267\270\352\263\241.java" "b/src/dami/programmers/level2/\353\260\251\352\270\210\352\267\270\352\263\241.java" new file mode 100644 index 0000000..bfd0fc2 --- /dev/null +++ "b/src/dami/programmers/level2/\353\260\251\352\270\210\352\267\270\352\263\241.java" @@ -0,0 +1,69 @@ +package dami.programmers.level2; + +import java.time.Duration; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +// https://programmers.co.kr/learn/courses/30/lessons/17683 + +// 주의할 점 1. C# D# F# G# A# 등 #음은 한 개 음으로 취급하기 +// 주의할 점 2. LocalTime 의 minusMinutes()는 시간 고려하지 않고 단순 minutes 차이만 계산 +// Duration의 between() 활용 +// 주의할 점 3. 재생시간까지 동일한 경우 먼저 입력된 음악을 반환해야하므로 순서 보장하는 LinkedHashMap 사용 +public class 방금그곡 { + private static final Map sharp; + + static { + sharp = new HashMap<>(); + sharp.put("C#", "c"); + sharp.put("D#", "d"); + sharp.put("F#", "f"); + sharp.put("G#", "g"); + sharp.put("A#", "a"); + } + + public String solution(String m, String[] musicinfos) { + String convertedM = convertSharpNote(m); + Map playInfo = new LinkedHashMap<>(); + for (String musicinfo : musicinfos) { + String[] info = musicinfo.split(","); + + int playTime = getPlayTime(info[0], info[1]); + System.out.println(playTime); + playInfo.put(info[2], getFullPlayNotes(info[3], playTime)); + } + + return playInfo.keySet().stream() + .sorted((key1, key2) -> playInfo.get(key2).length() - playInfo.get(key1).length()) + .filter(key -> playInfo.get(key).contains(convertedM)) + .findFirst() + .orElse("(None)"); + } + + private int getPlayTime(String start, String end) { + LocalTime startLdt = LocalTime.parse(start, DateTimeFormatter.ofPattern("HH:mm")); + LocalTime endLdt = LocalTime.parse(end, DateTimeFormatter.ofPattern("HH:mm")); + return (int) (Duration.between(startLdt, endLdt).getSeconds() / 60); + } + + private String getFullPlayNotes(String notes, int playTime) { + StringBuilder fullNotes = new StringBuilder(); + notes = convertSharpNote(notes); + for (int i = 0; i < playTime / notes.length(); i++) { + fullNotes.append(notes); + } + fullNotes.append(notes, 0, playTime % notes.length()); + + return fullNotes.toString(); + } + + private String convertSharpNote(String notes) { + for (String key : sharp.keySet()) { + notes = notes.replaceAll(key, sharp.get(key)); + } + return notes; + } +} diff --git "a/src/dami/programmers/level2/\354\202\274\352\260\201_\353\213\254\355\214\275\354\235\264.java" "b/src/dami/programmers/level2/\354\202\274\352\260\201_\353\213\254\355\214\275\354\235\264.java" new file mode 100644 index 0000000..ed29c60 --- /dev/null +++ "b/src/dami/programmers/level2/\354\202\274\352\260\201_\353\213\254\355\214\275\354\235\264.java" @@ -0,0 +1,105 @@ +package dami.programmers.level2; + +import java.util.stream.IntStream; + +// https://hongjuzzang.github.io/solution/code_p68645/ 참고 + +public class 삼각_달팽이 { + private static int[] answer; + private static int value = 1; + + public int[] solution(int n) { + answer = new int[snailSize(n)]; + int k = 0; // 루프 반복 횟수 + + while (n >= 1) { + fillArr(2 * k * (k + 1), 2 * k + 1, n, k); + n -= 3; + k++; + } + return answer; + } + + private void fillArr(int startIndex, int sub, int n, int k) { + if (n == 1) { + answer[startIndex] = value; + return; + } + + // 아래로 이동 + // 아래로 내려갈수록 인덱스는 +1 계차수열 + // 첫번쨰 내부 삼각형의 시작 인덱스는 4이고 초기값이 2*반복횟수+1 부터 시작하는 +1 계차수열 + // 두번째 내부 삼각형의 시작 인덱스는 8이고 초기값이 2*반복횟수+1 부터 시작하는 +1 계차수열, . . . + int index = startIndex; + int count = n - 1; // 밑변 제외 횟수 + while (count > 0) { + answer[index] = value++; + index += sub++; + count--; + } + + // 우측으로 이동 + for (int i = 0; i < n; i++) { + answer[index++] = value++; + } + + // 위로 이동 + // 위로 올라갈수록 인덱스는 n의 -1 계차수열 + // 첫번째 내부 삼각형은 올라갈수록 n-1의 -1 계차 + // 두번쨰 내부 삼각형은 올라갈수록 n-2의 -1 계차, . . . + index--; + int nk = (n + 3 * k) - k; // 최초 n에 반복횟수 만큼 차감 + for (int i = 0; i < n - 2; i++) { + index -= nk; + answer[index] = value++; + nk--; + } + } + + private int snailSize(int n) { + return IntStream.range(1, n + 1).sum(); + } +} + + +/* +// 생각하다 포기 +public class 삼각_달팽이 { + + public int[] solution(int n) { + int[] answer = new int[snailSize(n)]; + + int topIndex = 0; + int vertexIndex = -4; + int snailNo = 1; + while (n > 0) { + // 아래로 이동 + vertexIndex += 4; + for (int i = 1; i <= n && snailNo <= answer.length; snailNo++, vertexIndex += topIndex + i++) { + answer[vertexIndex] = snailNo; + } + + // 우로 이동 + vertexIndex -= (topIndex + n) - 1; + for (int i = 0; i < n - 1 && snailNo <= answer.length; snailNo++, vertexIndex++, i++) { + answer[vertexIndex] = snailNo; + } + + // 위로 이동 + vertexIndex -= n + 1; + for (int i = 0; i < n - 2 && snailNo <= answer.length; snailNo++, vertexIndex -= n - ++i) { + answer[vertexIndex] = snailNo; + } + + n -= 3; + topIndex += 2; + } + + return answer; + } + + private int snailSize(int n) { + return IntStream.range(1, n + 1).sum(); + } +} +*/ diff --git "a/src/dami/programmers/level2/\354\206\214\354\210\230\354\260\276\352\270\260.java" "b/src/dami/programmers/level2/\354\206\214\354\210\230\354\260\276\352\270\260.java" new file mode 100644 index 0000000..24e6444 --- /dev/null +++ "b/src/dami/programmers/level2/\354\206\214\354\210\230\354\260\276\352\270\260.java" @@ -0,0 +1,135 @@ +package dami.programmers.level2; + +import java.util.*; + + +// https://programmers.co.kr/learn/courses/30/lessons/42839/solution_groups?language=java&type=all +public class 소수찾기 { + public int solution(String numbers) { + HashSet numberSet = new HashSet<>(); + permutation("", numbers, numberSet); + + int count = 0; + while (numberSet.iterator().hasNext()) { + int number = numberSet.iterator().next(); + numberSet.remove(number); + + if (number == 2) { + count++; + } + if (number % 2 != 0 && isPrime(number)) { + count++; + } + } + return count; + } + + private boolean isPrime(int n) { + if (n == 0 || n == 1) { + return false; + } + for (int i = 3; i <= (int)Math.sqrt(n); i+=2) { + if (n % i == 0) { + return false; + } + } + return true; + } + + private void permutation(String prefix, String numbers, HashSet numberSet) { + int length = numbers.length(); + + if (!"".equals(prefix)) { + numberSet.add(Integer.valueOf(prefix)); + } + for (int i = 0; i < length; i++) { + permutation(prefix + numbers.charAt(i), numbers.substring(0, i) + numbers.substring(i+1, length), numberSet); + } + } +} + +/* +public class 소수찾기 { + private static final Set combiNumbers = new HashSet<>(); + + public int solution(String numbers) { + boolean[] visited = new boolean[numbers.length()]; + + for (int i = 1; i <= numbers.length(); i++) { + combination(numbers.toCharArray(), visited, 0, numbers.length(), i); + } + + return combiNumbers.size(); + } + + private void combination(char[] numbers, boolean[] visited, int start, int arrLength, int combiLength) { + if (combiLength == 0) { + addSet(numbers, visited, arrLength); + return; + } + + for (int i = start; i < arrLength; i++) { + visited[i] = true; + combination(numbers, visited, i + 1, arrLength, combiLength - 1); + visited[i] = false; + } + } + + private void addSet(char[] numbers, boolean[] visited, int length) { + StringBuilder combiNumber = new StringBuilder(); + for (int i = 0; i < visited.length; i++) { + if (visited[i]) { + combiNumber.append(numbers[i]); + } + } + + permutation(combiNumber.toString().toCharArray(), 0, combiNumber.length(), combiNumber.length()); + } + + private void permutation(char[] numbers, int depth, int arrayLength, int permCount) { + if (depth == permCount) { + addPermNumbers(numbers, permCount); + return; + } + for (int i = depth; i < arrayLength; i++) { + swap(numbers, depth, i); + permutation(numbers, depth + 1, arrayLength, permCount); + swap(numbers, depth, i); + } + } + + private void swap(char[] arr, int depth, int i) { + char temp = arr[depth]; + arr[depth] = arr[i]; + arr[i] = temp; + } + + private void addPermNumbers(char[] numbers, int length) { + StringBuilder permNumber = new StringBuilder(); + for (int i = 0; i < length; i++) { + permNumber.append(numbers[i]); + } + + int number = Integer.parseInt(String.valueOf(permNumber)); + + if (isPrimeNumber(number)) { + combiNumbers.add(number); + } + } + + private boolean isPrimeNumber(int number) { + if (number < 2) { + return false; + } + + int sqrt = (int)Math.sqrt(number); + while (sqrt > 1) { + if (number % sqrt == 0) { + return false; + } + sqrt--; + } + return true; + } +} +*/ diff --git "a/src/dami/programmers/level2/\354\210\230\354\213\235_\354\265\234\353\214\200\355\231\224.java" "b/src/dami/programmers/level2/\354\210\230\354\213\235_\354\265\234\353\214\200\355\231\224.java" new file mode 100644 index 0000000..ea5f1d9 --- /dev/null +++ "b/src/dami/programmers/level2/\354\210\230\354\213\235_\354\265\234\353\214\200\355\231\224.java" @@ -0,0 +1,96 @@ +package dami.programmers.level2; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +// https://programmers.co.kr/learn/courses/30/lessons/67257 + +// 1. 연산자 우선순위 조합 목록 만들기 +// 2. 피연산자, 연산자 분리해서 각각 LinkedList에 저장 +// 3. 우선순위 조합 목록 크기만큼 반복해서 수식 계산 +// 4. 계산 결과 최댓값 비교 +public class 수식_최대화 { + private static final String[] OPERATORS = new String[] {"+", "-", "*"}; + private static final String OPERATOR_PATTERN = Pattern.compile("[+*-]").pattern(); + private static final String OPERAND_PATTERN = Pattern.compile("[0-9]*").pattern(); + + public long solution(String expression) { + List priorities = new ArrayList<>(); + permutation(priorities, new StringBuilder(), 0); + + List operands = getAllOperands(expression); + List operators = getAllOperators(expression); + long max = 0; + + for (String priority : priorities) { + long sum = 0; + LinkedList exOperands = new LinkedList<>(operands); + LinkedList exOperators = new LinkedList<>(operators); + for (int i = 0; i < priority.length(); i++) { + String operator = String.valueOf(priority.charAt(i)); + while (exOperators.contains(operator)) { + int index = exOperators.indexOf(operator); + sum = calculate(exOperands.get(index), exOperands.remove(index + 1), exOperators.remove(index)); + exOperands.set(index, sum); + } + } + max = Math.max(max, Math.abs(sum)); + } + + return max; + } + + private List getAllOperands(String expression) { + return Arrays.stream(expression.split(OPERATOR_PATTERN)) + .mapToLong(Long::parseLong) + .boxed() + .collect(Collectors.toList()); + } + + private List getAllOperators(String expression) { + return Arrays.stream(expression.split(OPERAND_PATTERN)) + .filter(operator -> operator.length() != 0) + .collect(Collectors.toList()); + } + + private void permutation(List priorities, StringBuilder prefix, int depth) { + if (depth == OPERATORS.length) { + priorities.add(prefix.toString()); + return; + } + + for (int i = depth; i < OPERATORS.length; i++) { + prefix.append(OPERATORS[i]); + swap(i, depth); + permutation(priorities, prefix, depth + 1); + prefix.deleteCharAt(prefix.length() - 1); + swap(i, depth); + } + } + + private void swap(int depth, int i) { + String temp = OPERATORS[depth]; + OPERATORS[depth] = OPERATORS[i]; + OPERATORS[i] = temp; + } + + private long calculate(long operand1, long operand2, String operator) { + long result = 0; + switch (operator) { + case "+": result = operand1 + operand2; + break; + case "-": result = operand1 - operand2; + break; + case "*": result = operand1 * operand2; + break; + default: break; + } + return result; + } + +} diff --git "a/src/dami/programmers/level2/\354\210\253\354\236\220\354\235\230_\355\221\234\355\230\204.java" "b/src/dami/programmers/level2/\354\210\253\354\236\220\354\235\230_\355\221\234\355\230\204.java" new file mode 100644 index 0000000..ee12c6e --- /dev/null +++ "b/src/dami/programmers/level2/\354\210\253\354\236\220\354\235\230_\355\221\234\355\230\204.java" @@ -0,0 +1,33 @@ +package dami.programmers.level2; + +public class 숫자의_표현 { + public int solution(int n) { + int answer = 1; + + for (int i = 1; i <= n / 2; i++) { + int sum = 0; + for (int j = i; sum < n; j++) { + sum += j; + + if (sum == n) { + answer++; + break; + } + } + } + return answer; + } + + // 주어진 자연수를 연속된 자연수의 합으로 표현하는 방법의 수는 주어진 수의 홀수 약수의 개수와 같다라는 정수론 정리가 있습니다. + public int solution2(int n) { + int answer = 0; + for (int i = 1; i <= n; i += 2) + if (n % i == 0) + answer++; + return answer; + } + + public static void main(String[] args) { + System.out.println(new 숫자의_표현().solution2(15)); + } +} diff --git "a/src/dami/programmers/level2/\354\225\225\354\266\225.java" "b/src/dami/programmers/level2/\354\225\225\354\266\225.java" new file mode 100644 index 0000000..fa55ead --- /dev/null +++ "b/src/dami/programmers/level2/\354\225\225\354\266\225.java" @@ -0,0 +1,60 @@ +package dami.programmers.level2; + +import java.util.*; + +// https://programmers.co.kr/learn/courses/30/lessons/17684 + +// 풀이 방법이 문제 설명에 나와있어서 금방 풀 수 있을줄 알았는데 생각보다 오래 걸린 문제 +// 조건처리를 깔끔하게 해주지 못한 느낌이고, 그냥 처음에 A-Z까지 해시맵에 초기화 해놓고 이후 단어들 추가하는 방법으로 구현하는게 나았을까 싶음ㅜㅜ + +// 1. offset에 압축할 단어 시작 위치 지정 +// 2. 현재 문자의 색인값 조회 +// offset이 마지막 문자를 가리키고 있으면 반복 중단 +// 4. 색인값 확인했을 때 한자리 문자면 현재문자+다음문자 사전에 추가 +// 두자리 이상 문자면 마지막 문자열인지 확인하고, 아닐 경우 현재문자열+다음문자 사전에 추가 +public class 압축 { + public int[] solution(String msg) { + List result = new ArrayList<>(); + List addition = new ArrayList<>(); + + String subMsg; + int offset = 0; + int index; + while (offset < msg.length()) { + subMsg = msg.substring(offset); + index = getDictionaryIndex(subMsg, addition); + result.add(index); + + if (offset == msg.length() - 1) { + break; + } + + if (index < 27) { + addition.add(subMsg.substring(0, 2)); + offset++; + } else { + int length = addition.get(index - 27).length(); + if (length == subMsg.length()) { + break; + } + addition.add(subMsg.substring(0, length + 1)); + offset += length; + } + } + + return result.stream() + .mapToInt(r -> r) + .toArray(); + } + + private int getDictionaryIndex(String msg, List addition) { + int index = msg.charAt(0) - 'A' + 1; + for (int i = 0; i < addition.size(); i++) { + if (msg.startsWith(addition.get(i))) { + index = i + 27; + } + } + return index; + } + +} diff --git "a/src/dami/programmers/level2/\354\230\201\354\226\264_\353\201\235\353\247\220\354\236\207\352\270\260.java" "b/src/dami/programmers/level2/\354\230\201\354\226\264_\353\201\235\353\247\220\354\236\207\352\270\260.java" new file mode 100644 index 0000000..67a1c54 --- /dev/null +++ "b/src/dami/programmers/level2/\354\230\201\354\226\264_\353\201\235\353\247\220\354\236\207\352\270\260.java" @@ -0,0 +1,33 @@ +package dami.programmers.level2; + +import java.util.*; + +public class 영어_끝말잇기 { + public int[] solution(int n, String[] words) { + int[] answer = new int[2]; + int number; + Set wordSet = new HashSet<>(); + for (int i = 0; i < words.length; i++) { + number = i + 1; + String word = words[i]; + if (wordSet.contains(word) || (i > 0 && !words[i - 1].endsWith(word.substring(0, 1)))) { + if (number % n == 0) { + answer[0] = n; + answer[1] = number / n; + } else { + answer[0] = number % n; + answer[1] = number / n + 1; + } + return answer; + } + wordSet.add(word); + } + + return answer; + } + + public static void main(String[] args) { + int[] answer = new 영어_끝말잇기().solution(2, new String[]{"land", "dream", "mom", "mom", "ror"}); + System.out.println(Arrays.toString(answer)); + } +} diff --git "a/src/dami/programmers/level2/\354\230\210\354\203\201_\353\214\200\354\247\204\355\221\234.java" "b/src/dami/programmers/level2/\354\230\210\354\203\201_\353\214\200\354\247\204\355\221\234.java" new file mode 100644 index 0000000..4880dcf --- /dev/null +++ "b/src/dami/programmers/level2/\354\230\210\354\203\201_\353\214\200\354\247\204\355\221\234.java" @@ -0,0 +1,29 @@ +package dami.programmers.level2; + +// https://programmers.co.kr/learn/courses/30/lessons/12985 + +public class 예상_대진표 { + public int solution(int n, int a, int b) { + int round = 1; + while (divide(a) != divide(b)) { + a = divide(a); + b = divide(b); + round++; + } + + return round; + } + + private int divide(int a) { + return (a + 1) / 2; + } +} + +/* // 다른 풀이 + +public int solution(int n, int a, int b) +{ + return Integer.toBinaryString((a-1)^(b-1)).length(); +} + +*/ diff --git "a/src/dami/programmers/level2/\354\230\244\355\224\210\354\261\204\355\214\205\353\260\251.java" "b/src/dami/programmers/level2/\354\230\244\355\224\210\354\261\204\355\214\205\353\260\251.java" new file mode 100644 index 0000000..bcfb0dd --- /dev/null +++ "b/src/dami/programmers/level2/\354\230\244\355\224\210\354\261\204\355\214\205\353\260\251.java" @@ -0,0 +1,41 @@ +package dami.programmers.level2; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +// https://programmers.co.kr/learn/courses/30/lessons/42888 +public class 오픈채팅방 { + private static final String[] COMMAND = new String[]{"Enter", "Leave", "Change"}; + private static final Map MESSAGES = new HashMap<>(); + static { + MESSAGES.put("Enter", "님이 들어왔습니다"); + MESSAGES.put("Leave", "님이 나갔습니다."); + } + + public String[] solution(String[] record) { + Map userMap = new HashMap<>(); + List results = new ArrayList<>(); + + for (String r : record) { + String[] line = r.split(" "); + if (!line[0].equals(COMMAND[1])) { + userMap.put(line[1], line[2]); + } + + if (!line[0].equals(COMMAND[2])) { + results.add(new StringBuilder(line[1] + MESSAGES.get(line[0]))); + } + } + + for (StringBuilder result : results) { + int uidLength = result.indexOf("님"); + result.replace(0, uidLength, userMap.get(result.substring(0, uidLength))); + } + + return results.stream() + .map(StringBuilder::toString) + .toArray(String[]::new); + } +} diff --git "a/src/dami/programmers/level2/\354\230\254\353\260\224\353\245\270_\352\264\204\355\230\270.java" "b/src/dami/programmers/level2/\354\230\254\353\260\224\353\245\270_\352\264\204\355\230\270.java" new file mode 100644 index 0000000..7c8f14c --- /dev/null +++ "b/src/dami/programmers/level2/\354\230\254\353\260\224\353\245\270_\352\264\204\355\230\270.java" @@ -0,0 +1,24 @@ +package dami.programmers.level2; + +import java.util.Stack; + +public class 올바른_괄호 { + boolean solution(String s) { + Stack brackets = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + char current = s.charAt(i); + + if (current == '(') { + brackets.push(current); + continue; + } + if (current == ')') { + if (brackets.isEmpty()) { + return false; + } + brackets.pop(); + } + } + return brackets.isEmpty(); + } +} diff --git "a/src/dami/programmers/level2/\354\232\224\352\262\251_\354\213\234\354\212\244\355\205\234.java" "b/src/dami/programmers/level2/\354\232\224\352\262\251_\354\213\234\354\212\244\355\205\234.java" new file mode 100644 index 0000000..dcffbf9 --- /dev/null +++ "b/src/dami/programmers/level2/\354\232\224\352\262\251_\354\213\234\354\212\244\355\205\234.java" @@ -0,0 +1,23 @@ +package dami.programmers.level2; + +import java.util.Arrays; +import java.util.Comparator; + +public class 요격_시스템 { + + public int solution(int[][] targets) { + Arrays.sort(targets, Comparator.comparing(target -> target[1])); + + int result = 0; + double last = -1.0; + for (int[] target : targets) { + if (target[0] < last) { + continue; + } + + result++; + last = target[1] - 0.1; + } + return result; + } +} diff --git "a/src/dami/programmers/level2/\354\235\264\354\247\204_\353\263\200\355\231\230_\353\260\230\353\263\265\355\225\230\352\270\260.java" "b/src/dami/programmers/level2/\354\235\264\354\247\204_\353\263\200\355\231\230_\353\260\230\353\263\265\355\225\230\352\270\260.java" new file mode 100644 index 0000000..91fb392 --- /dev/null +++ "b/src/dami/programmers/level2/\354\235\264\354\247\204_\353\263\200\355\231\230_\353\260\230\353\263\265\355\225\230\352\270\260.java" @@ -0,0 +1,58 @@ +package dami.programmers.level2; + + +// https://programmers.co.kr/learn/courses/30/lessons/70129 + +// 1. 주어진 문자열(이진수 문자열)에서 replaceAll 사용해서 0 없애고, 문자열 길이 비교로 제거한 0개수 확인 +// 2. 1의 개수를 이진수 문자열로 변환 +// 1, 2 반복 +public class 이진_변환_반복하기 { + public int[] solution(String s) { + int oneCount = s.length(); + int zeroCount = 0; + int iteration = 0; + while (!(oneCount == 1 && s.contains(("1")))) { + iteration++; + oneCount = s.replaceAll("0", "").length(); + if (s.contains("0")) { + zeroCount += s.length() - oneCount; + } + s = convertBinaryString(oneCount); + } + + return new int[] {iteration, zeroCount}; + } + + private String convertBinaryString(int number) { + StringBuilder result = new StringBuilder(); + int remain; + while (number > 1) { + remain = number % 2; + number /= 2; + result.insert(0, remain); + } + result.insert(0, number); + return result.toString(); + } + + + public static void main(String[] args) { + new 이진_변환_반복하기().solution_2023("111111"); + } + + + public int[] solution_2023(String s) { + int numberOfConvert = 0; + int numberOfZero = 0; + while (!s.equals("1")) { + int originLength = s.length(); + String removedS = s.replaceAll("0", ""); + numberOfZero += originLength - removedS.length(); + + s = Integer.toBinaryString(removedS.length()); + numberOfConvert++; + } + + return new int[] {numberOfConvert, numberOfZero}; + } +} diff --git "a/src/dami/programmers/level2/\354\240\220\355\224\204\354\231\200_\354\210\234\352\260\204_\354\235\264\353\217\231.java" "b/src/dami/programmers/level2/\354\240\220\355\224\204\354\231\200_\354\210\234\352\260\204_\354\235\264\353\217\231.java" new file mode 100644 index 0000000..baa95b8 --- /dev/null +++ "b/src/dami/programmers/level2/\354\240\220\355\224\204\354\231\200_\354\210\234\352\260\204_\354\235\264\353\217\231.java" @@ -0,0 +1,19 @@ +package dami.programmers.level2; + +//https://programmers.co.kr/learn/courses/30/lessons/12980 + +public class 점프와_순간_이동 { + + public int solution(int n) { + int result = 0; + + while (n > 1) { + if (n % 2 != 0) { + result++; + } + n /= 2; + } + + return ++result; + } +} diff --git "a/src/dami/programmers/level2/\354\247\235\354\247\200\354\226\264_\354\240\234\352\261\260\355\225\230\352\270\260.java" "b/src/dami/programmers/level2/\354\247\235\354\247\200\354\226\264_\354\240\234\352\261\260\355\225\230\352\270\260.java" new file mode 100644 index 0000000..985333b --- /dev/null +++ "b/src/dami/programmers/level2/\354\247\235\354\247\200\354\226\264_\354\240\234\352\261\260\355\225\230\352\270\260.java" @@ -0,0 +1,38 @@ +package dami.programmers.level2; + +import java.util.Stack; + +// https://programmers.co.kr/learn/courses/30/lessons/12973 +public class 짝지어_제거하기 { + public int solution_2020(String s) { + Stack stack = new Stack<>(); + stack.push(s.charAt(0)); + for (int i = 1; i < s.length(); i++) { + if (!stack.isEmpty() && stack.peek() == s.charAt(i)) { + stack.pop(); + } else { + stack.push(s.charAt(i)); + } + } + return stack.size() > 0 ? 0 : 1; + } + + public int solution_2023(String s) { + // baabaa cdcd stack? + Stack stack = new Stack<>(); + char[] chars = s.toCharArray(); + for (char c : chars) { + if (!stack.isEmpty() && stack.peek() == c) { + stack.pop(); + } else { + stack.push(c); + } + } + + return stack.isEmpty() ? 1 : 0; + } + + public static void main(String[] args) { + System.out.println(new 짝지어_제거하기().solution_2023("a")); + } +} diff --git "a/src/dami/programmers/level2/\354\265\234\353\214\223\352\260\222\352\263\274_\354\265\234\354\206\237\352\260\222.java" "b/src/dami/programmers/level2/\354\265\234\353\214\223\352\260\222\352\263\274_\354\265\234\354\206\237\352\260\222.java" new file mode 100644 index 0000000..ec21a1e --- /dev/null +++ "b/src/dami/programmers/level2/\354\265\234\353\214\223\352\260\222\352\263\274_\354\265\234\354\206\237\352\260\222.java" @@ -0,0 +1,16 @@ +package dami.programmers.level2; + +public class 최댓값과_최솟값 { + public String solution(String s) { + String[] integers = s.split(" "); + + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + for (String integer : integers) { + min = Math.min(min, Integer.parseInt(integer)); + max = Math.max(max, Integer.parseInt(integer)); + } + + return min + " " + max; + } +} diff --git "a/src/dami/programmers/level2/\354\265\234\354\206\237\352\260\222_\353\247\214\353\223\244\352\270\260.java" "b/src/dami/programmers/level2/\354\265\234\354\206\237\352\260\222_\353\247\214\353\223\244\352\270\260.java" new file mode 100644 index 0000000..05d8e58 --- /dev/null +++ "b/src/dami/programmers/level2/\354\265\234\354\206\237\352\260\222_\353\247\214\353\223\244\352\270\260.java" @@ -0,0 +1,92 @@ +package dami.programmers.level2; + +// https://programmers.co.kr/learn/courses/30/lessons/12941 + +import java.util.Arrays; + +public class 최솟값_만들기 { + public int solution(int []A, int []B) { + Arrays.sort(A); + Arrays.sort(B); + + int sum = 0; + for (int i = 0; i < A.length; i++) { + sum += A[i] * B[B.length - i - 1]; + } + + return sum; + } + + // 정렬 알고리즘 연습 (퀵 정렬) + private void ascSort(int[] array) { + recursiveAsc(array, 0, array.length - 1); + } + + private void recursiveAsc(int[] array, int start, int end) { + if (end - start <= 0) { + return; + } + + int low = start + 1; + int high = end; + int pivot = array[start]; + while (low <= high) { + while (low <= high && pivot > array[low]) { // pivot보다 큰 값 찾을 때까지 이동 + low++; + } + + while (pivot < array[high]) { // pivot보다 작은 값 찾을 때까지 이동 + high--; + } + + if (low <= high) { + swap(array, low, high); + } + } + + if (start < end) { + swap(array, start, high); + recursiveAsc(array, start, high - 1); + recursiveAsc(array, high + 1, end); + } + } + + private void descSort(int[] array) { + recursiveDesc(array, 0, array.length - 1); + } + + private void recursiveDesc(int[] array, int start, int end) { + if (end - start <= 0) { + return; + } + + int low = start + 1; + int high = end; + int pivot = array[start]; + while (low <= high) { + while (low <= high && pivot < array[low]) { // pivot보다 작은 array 값 찾을 때까지 이동 + low++; + } + + while (pivot > array[high]) { // pivot보다 큰 array 값 찾을 때까지 이동 + high--; + } + + if (low <= high) { + swap(array, low, high); + } + } + + if (start < end) { + swap(array, start, high); + recursiveDesc(array, start, high - 1); + recursiveDesc(array, high + 1, end); + } + } + + private void swap(int[] array, int low, int high) { + int temp = array[low]; + array[low] = array[high]; + array[high] = temp; + } +} diff --git "a/src/dami/programmers/level2/\354\271\264\354\271\264\354\230\244\355\224\204\353\240\214\354\246\210_\354\273\254\353\237\254\353\247\201\353\266\201.java" "b/src/dami/programmers/level2/\354\271\264\354\271\264\354\230\244\355\224\204\353\240\214\354\246\210_\354\273\254\353\237\254\353\247\201\353\266\201.java" new file mode 100644 index 0000000..02879d9 --- /dev/null +++ "b/src/dami/programmers/level2/\354\271\264\354\271\264\354\230\244\355\224\204\353\240\214\354\246\210_\354\273\254\353\237\254\353\247\201\353\266\201.java" @@ -0,0 +1,76 @@ +package dami.programmers.level2; + +import java.util.Stack; + +public class 카카오프렌즈_컬러링북 { + + public int[] solution(int m, int n, int[][] picture) { + int numberOfArea = 0; + int maxSizeOfOneArea = 0; + + boolean[][] visited = new boolean[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + visited[i][j] = false; + } + } + + Stack pointX = new Stack<>(); + Stack pointY = new Stack<>(); + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + int sizeOfOneArea = 0; + if ((long) picture[i][j] == 0 || visited[i][j]) { + continue; + } + + pointX.push(j); + pointY.push(i); + visited[i][j] = true; + numberOfArea++; + sizeOfOneArea++; + + while (!pointX.isEmpty()) { + int x = pointX.pop(); + int y = pointY.pop(); + + // 위 이동 + if (y > 0 && (long) picture[i][j] == (long) picture[y-1][x] && !visited[y-1][x]) { + pointX.push(x); + pointY.push(y-1); + visited[y-1][x] = true; + sizeOfOneArea++; + } + // 좌측 이동 + if (x > 0 && (long) picture[i][j] == (long) picture[y][x-1] && !visited[y][x-1]) { + pointX.push(x-1); + pointY.push(y); + visited[y][x-1] = true; + sizeOfOneArea++; + } + // 우측 이동 + if (x < n-1 && (long) picture[i][j] == (long) picture[y][x+1] && !visited[y][x+1]) { + pointX.push(x+1); + pointY.push(y); + visited[y][x+1] = true; + sizeOfOneArea++; + } + // 아래 이동 + if (y < m-1 && (long) picture[i][j] == (long) picture[y+1][x] && !visited[y+1][x]) { + pointX.push(x); + pointY.push(y+1); + visited[y+1][x] = true; + sizeOfOneArea++; + } + } + maxSizeOfOneArea = Math.max(maxSizeOfOneArea, sizeOfOneArea); + } + } + + int[] answer = new int[2]; + answer[0] = numberOfArea; + answer[1] = maxSizeOfOneArea; + return answer; + } + +} diff --git "a/src/dami/programmers/level2/\354\271\264\355\216\253.java" "b/src/dami/programmers/level2/\354\271\264\355\216\253.java" new file mode 100644 index 0000000..08b42f6 --- /dev/null +++ "b/src/dami/programmers/level2/\354\271\264\355\216\253.java" @@ -0,0 +1,32 @@ +package dami.programmers.level2; + +import java.util.Arrays; + +public class 카펫 { + public int[] solution(int brown, int yellow) { + int[] answer = {}; + for (int i = 1; i <= yellow / i; i++) { + if (yellow % i == 0) { + int height = i + 2; + int width = (yellow / i) + 2; + + int round = (width + height) * 2 - 4; + if (brown == round) { + return new int[]{width, height}; + } + } + } + return answer; + } + + public int[] solution_wow(int brown, int red) { + int a = (brown+4)/2; + int b = red+2*a-4; + int[] answer = {(int)(a+Math.sqrt(a*a-4*b))/2,(int)(a-Math.sqrt(a*a-4*b))/2}; + return answer; + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(new 카펫().solution(24, 24))); + } +} diff --git "a/src/dami/programmers/level2/\354\272\220\354\213\234.java" "b/src/dami/programmers/level2/\354\272\220\354\213\234.java" new file mode 100644 index 0000000..99d26da --- /dev/null +++ "b/src/dami/programmers/level2/\354\272\220\354\213\234.java" @@ -0,0 +1,105 @@ +package dami.programmers.level2; + +import java.util.LinkedList; +import java.util.Queue; + +// https://programmers.co.kr/learn/courses/30/lessons/17680 +public class 캐시 { + public int solution(int cacheSize, String[] cities) { + if (cacheSize == 0) { + return cities.length * 5; + } + + int time = 0; + Queue cache = new LinkedList<>(); + for (String city : cities) { + city = city.toLowerCase(); + + if (cache.contains(city)) { + time++; + cache.remove(city); + } else { + time += 5; + } + + if (cache.size() == cacheSize) { + cache.poll(); + } + cache.offer(city); + } + + return time; + } + +} + +/* // 다른 풀이 1 + // LRU 알고리즘 효율을 위해 Map 사용 + +class Solution { + public int solution(int cacheSize, String[] cities) { + int answer = 0; + LRU clsTemp = LRU.newInstance(cacheSize); + for (int i = 0; i < cities.length; i++) { + String sTemp = cities[i].toUpperCase(); + if(clsTemp.containsKey(sTemp)) { + answer++; + }else { + answer +=5; + } + clsTemp.put(sTemp, sTemp); + } + + return answer; + } +} + +class LRU extends LinkedHashMap { + private int size; + + private LRU(int size) { + super(size, 0.75f, true); + this.size = size; + } + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > size; + } + public static LRU newInstance(int size) { + return new LRU(size); + } +} + +*/ + + +/* // 다른 풀이 2 + // removeFirstOccurrence(Object o) == remove(Object o) + // => 값 제거 성공하면 true / 실패하면 false 반환하는 것 이용해서 cache hit 여부 확인한 풀이 + // 참고로 removeLastOccurrence()도 있음 +class Solution { + public int solution(int cacheSize, String[] cities) { + int time = 0; + + if (cacheSize == 0) { + return cities.length * 5; + } + + Queue queue = new LinkedList<>(); + for (int i = 0; i < cities.length; i++) { + boolean hit = ((LinkedList) queue).removeFirstOccurrence(cities[i].toUpperCase()); + queue.add(cities[i].toUpperCase()); + time += 1; + if (!hit) { + time += 4; + if (queue.size() > cacheSize) { + String removed = ((LinkedList) queue).removeFirst(); + } + } + } + + int answer = time; + return answer; + } +} + +*/ diff --git "a/src/dami/programmers/level2/\355\203\200\352\262\237_\353\204\230\353\262\204.java" "b/src/dami/programmers/level2/\355\203\200\352\262\237_\353\204\230\353\262\204.java" new file mode 100644 index 0000000..2f069f1 --- /dev/null +++ "b/src/dami/programmers/level2/\355\203\200\352\262\237_\353\204\230\353\262\204.java" @@ -0,0 +1,49 @@ +package dami.programmers.level2; + +import java.util.Arrays; + +// https://programmers.co.kr/learn/courses/30/lessons/43165?language=java + +// 1. 주어진 배열의 총 합 계산 +// 2. '총 합 - 타겟 값'이 각 원소의 누적 두 배 값과 같으면 결과 + 1 (총 합 - 원소 두 배 값(누적) == 타겟인 경우 찾기) +// 보다 크면 총 합에서 원소 두 배 값 빼주고 다음값과 비교하도록 재귀 호출 + +// 다른 풀이와 유사하지만 나는 로직을 꼬아서 푼 듯 +public class 타겟_넘버 { + public int solution(int[] numbers, int target) { + int sum = Arrays.stream(numbers).sum(); + return recursive(sum - target, 0, numbers, 0); + } + + private int recursive(int currentSum, int currentIndex, int[] numbers, int result) { + if (currentSum == 0) { + return result + 1; + } + + for (int i = currentIndex; i < numbers.length; i++) { + if (currentSum >= numbers[i] * 2 ) { + result = recursive(currentSum - numbers[i] * 2, i + 1, numbers, result); + } + } + + return result; + } +} +/* // 다른 풀이 +class Solution { + public int solution(int[] numbers, int target) { + int answer = 0; + answer = dfs(numbers, 0, 0, target); + return answer; + } + int dfs(int[] numbers, int n, int sum, int target) { + if(n == numbers.length) { + if(sum == target) { + return 1; + } + return 0; + } + return dfs(numbers, n + 1, sum + numbers[n], target) + dfs(numbers, n + 1, sum - numbers[n], target); + } +} +*/ diff --git "a/src/dami/programmers/level2/\355\212\234\355\224\214.java" "b/src/dami/programmers/level2/\355\212\234\355\224\214.java" new file mode 100644 index 0000000..eb93c30 --- /dev/null +++ "b/src/dami/programmers/level2/\355\212\234\355\224\214.java" @@ -0,0 +1,34 @@ +package dami.programmers.level2; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +// https://programmers.co.kr/learn/courses/30/lessons/64065 + +// 1. 중괄호 제거 +// 2. 쉼표로 split +// {{4,2,3},{3},{2,3,4,1},{2,3}} +// 4,2,3,3,2,3,4,1,2,3 +// 3. HashMap에 put +// key : 각 숫자, value : 숫자 빈도수 +// 4. 빈도수 오름차순 정렬해서 return + +public class 튜플 { + public int[] solution(String s) { + s = s.replaceAll("\\{", "") + .replaceAll("}", ""); + + String[] numbers = s.split(","); + Map numberCountMap = new HashMap<>(); + for(String number : numbers) { + numberCountMap.put(number, numberCountMap.getOrDefault(number, 0) + 1); + } + + return numberCountMap.keySet() + .stream() + .sorted((key1, key2) -> numberCountMap.get(key2).compareTo(numberCountMap.get(key1))) + .mapToInt(Integer::parseInt) + .toArray(); + } +} diff --git "a/src/dami/programmers/level2/\355\214\214\354\235\274\353\252\205_\354\240\225\353\240\254.java" "b/src/dami/programmers/level2/\355\214\214\354\235\274\353\252\205_\354\240\225\353\240\254.java" new file mode 100644 index 0000000..c9d348f --- /dev/null +++ "b/src/dami/programmers/level2/\355\214\214\354\235\274\353\252\205_\354\240\225\353\240\254.java" @@ -0,0 +1,157 @@ +package dami.programmers.level2; + + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Pattern; + +// https://programmers.co.kr/learn/courses/30/lessons/17686 + +// 정렬 기준에 따라 차이가 없다면 원래 입력에서 주어진 순서를 유지하는 안정 정렬 +// 안정 정렬 O : 병합, 버블, 삽입 +// 안정 정렬 X : 퀵 +// C++과 Python에는 안정 정렬이 있고, Java와 JavaScript, Swift에는 안정 정렬이 없음 +// 안정 정렬을 지원하지 않거나, 이 문제처럼 비교 조건이 까다로운 경우에는 decorate-sort-undecorate 패턴을 이용해서 쉽게 해결할 수도 + +// 1. key는 파일명, value는 각각 head와 number를 가지는 headMap, numberMap 생성 +// 2. 각각 head와 number부 분리해서 저장 +// 3. 조건에 맞게 정렬해서 결과 반환 +public class 파일명_정렬 { + private static final int MAX_NUMBER_SIZE = 5; + private static final String NUMBER = Pattern.compile("[0-9]{1,5}").pattern(); + private static final String CHARACTER = Pattern.compile("[\\sa-z.-]").pattern(); + + public String[] solution(String[] files) { + Map headMap = new LinkedHashMap<>(); + Map numberMap = new LinkedHashMap<>(); + for (String file : files) { + String[] split = file.split(NUMBER); + headMap.put(file, split[0].toLowerCase()); + numberMap.put(file, splitNumber(file, split)); + } + + return headMap.keySet().stream() + .sorted((key1, key2) -> { + if (headMap.get(key1).equals(headMap.get(key2))) { + return numberMap.get(key1) - numberMap.get(key2); + } + return headMap.get(key1).compareTo(headMap.get(key2)); + }) + .toArray(String[]::new); + } + + // 1. 숫자부분 Math.min(문자열 길이, 5)자리까지 자르기 + // 2. 숫자 정규식으로 문자 목록 분리한 String 배열 크기가 1인 경우 (img000, img0000000) 그대로 반환 + // 3. 배열 크기가 2 이상인 경우 문자 정규식으로 숫자 목록 분리한 배열의 첫번째 값 반환 + private Integer splitNumber(String file, String[] split) { + String numberString = file.substring(split[0].length(), Math.min(file.length(), MAX_NUMBER_SIZE + split[0].length())); + if (split.length < 2) { + return Integer.parseInt(numberString); + } + + return Integer.parseInt(numberString.split(CHARACTER)[0]); + } + +} + + +/* // 다른 풀이. Matcher 클래스 활용 + +class Solution { + public String[] solution(String[] files) { + List fileNameList = new ArrayList<>(); + String head, number, tail; + + for (int i = 0; i < files.length; i++) { + String s = files[i]; + Pattern p = Pattern.compile("[0-9]+"); + Matcher m = p.matcher(s); + if (m.find()){ + number = m.group(); + int numberStartIndex = s.indexOf(number); + head = s.substring(0, numberStartIndex); + int numberEndIndex = numberStartIndex + number.length() - 1; + if (numberEndIndex + 1 > s.length() - 1) { + tail = ""; + } else { + tail = s.substring(numberEndIndex + 1); + } + fileNameList.add(new FileName(head, number, tail)); + } + } + + fileNameList.sort(Comparator.comparing(FileName::getHead).thenComparing(Comparator.naturalOrder())); + + String[] answer = new String[files.length]; + for (int i = 0; i < files.length; i++) { + answer[i] = fileNameList.get(i).toString(); + } + return answer; + } + + public static class FileName implements Comparable { + String head; + String number; + String tail; + + public FileName(String head, String number, String tail) { + this.head = head; + this.number = number; + this.tail = tail; + } + + public String getHead() { + return head.toUpperCase(); + } + + @Override + public String toString() { + return head + number + tail; + } + + @Override + public int compareTo(FileName o) { + int mine = Integer.parseInt(this.number); + int yours = Integer.parseInt(o.number); + return mine - yours; + } + } +} + +*/ + + +/* // 다른 풀이 + +class Solution { + public String[] solution(String[] files) { + Arrays.sort(files, new StrCmp()); + return files; + } + private class StrCmp implements Comparator { + @Override + public int compare(String s1, String s2) { + s1 = s1.toLowerCase(); + s2 = s2.toLowerCase(); + + // 문자열 비교 + int i = 0; + int j = 0; + while (i < s1.length() && !Character.isDigit(s1.charAt(i))) ++i; + while (j < s2.length() && !Character.isDigit(s2.charAt(j))) ++j; + int cmp1 = s1.substring(0, i).compareTo(s2.substring(0, j)); + if (cmp1 != 0) return cmp1; + + // 숫자 비교 + int startI = i; + int startJ = j; + while (i < s1.length() && Character.isDigit(s1.charAt(i))) ++i; + while (j < s2.length() && Character.isDigit(s2.charAt(j))) ++j; + int num1 = Integer.parseInt(s1.substring(startI, i)); + int num2 = Integer.parseInt(s2.substring(startJ, j)); + return num1 - num2; + } + } +} + +*/ diff --git "a/src/dami/programmers/level2/\355\217\260\354\274\223\353\252\254.java" "b/src/dami/programmers/level2/\355\217\260\354\274\223\353\252\254.java" new file mode 100644 index 0000000..b6ea75b --- /dev/null +++ "b/src/dami/programmers/level2/\355\217\260\354\274\223\353\252\254.java" @@ -0,0 +1,22 @@ +package dami.programmers.level2; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +// https://programmers.co.kr/learn/courses/30/lessons/1845 + +// 1. 최대 종류 수는 nums.length / 2 +// 2. 주어진 배열을 set에 저장 +// 3. set의 크기와 최대 종류 수 중 작은 값 return + +public class 폰켓몬 { + public int solution(int[] nums) { + int maxType = nums.length / 2; + Set numSet = Arrays.stream(nums) + .boxed() + .collect(Collectors.toSet()); + + return Math.min(numSet.size(), maxType); + } +} diff --git "a/src/dami/programmers/level2/\355\224\274\353\263\264\353\202\230\354\271\230_\354\210\230.java" "b/src/dami/programmers/level2/\355\224\274\353\263\264\353\202\230\354\271\230_\354\210\230.java" new file mode 100644 index 0000000..60b284b --- /dev/null +++ "b/src/dami/programmers/level2/\355\224\274\353\263\264\353\202\230\354\271\230_\354\210\230.java" @@ -0,0 +1,30 @@ +package dami.programmers.level2; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +public class 피보나치_수 { + + private static final int[] FIVO = new int[100001]; + + public int solution(int n) { + Arrays.fill(FIVO, -1); + for (int i = 0; i <= n; i++) { + fivo(i); + } + return FIVO[n]; + } + + private int fivo(int n) { + if (FIVO[n] != -1) return FIVO[n]; + if (n == 0) return 0; + if (n == 1) return 1; + + return FIVO[n] = (fivo(n - 1) + fivo(n - 2)) % 1234567; + } + + public static void main(String[] args) { + System.out.println(new 피보나치_수().solution(100000)); + } +} diff --git "a/src/dami/programmers/level3/review/\353\223\261\352\265\243\352\270\270.java" "b/src/dami/programmers/level3/review/\353\223\261\352\265\243\352\270\270.java" new file mode 100644 index 0000000..da1607a --- /dev/null +++ "b/src/dami/programmers/level3/review/\353\223\261\352\265\243\352\270\270.java" @@ -0,0 +1,83 @@ +package dami.programmers.level3.review; + +import java.util.LinkedList; +import java.util.Queue; + +// https://programmers.co.kr/learn/courses/30/lessons/42898 +public class 등굣길 { + public int solution(int m, int n, int[][] puddles) { + //return bfs(m, n, puddles); + return dp(m, n, puddles); + } + + // 시간 초과 + private int bfs(int m, int n, int[][] puddles) { + boolean[][] water = new boolean[n][m]; + + for (int[] puddle : puddles) { + water[puddle[1] - 1][puddle[0] - 1] = true; + } + + Queue points = new LinkedList<>(); + points.offer(new Point(1, 1)); + + int result = 0; + while (!points.isEmpty()) { + Point point = points.poll(); + int x = point.x; + int y = point.y; + + if (y < m && !water[x - 1][y]) { + points.offer(new Point(x, y + 1)); + } + + if (x < n && !water[x][y - 1]) { + points.offer(new Point(x + 1, y)); + } + + + if (x == n && y == m) { + result++; + } + } + + return result; + } + + // 예전에 배웠던 최단 경로 구하는 방법 그대로 구현하면 되는 문제 ..... + // 오버플로우 주의 + private int dp(int m, int n, int[][] puddles) { + int[][] path = new int[n][m]; + + for (int[] puddle : puddles) { + path[puddle[1] - 1][puddle[0] - 1] = -1; + } + + path[0][0] = 1; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (path[i][j] == -1) { + path[i][j] = 0; + continue; + } + + if (i > 0) path[i][j] += path[i - 1][j] % 1_000_000_007; + if (j > 0) path[i][j] += path[i][j - 1] % 1_000_000_007; + } + } + + return path[n - 1][m - 1] % 1_000_000_007; + } +} + +class Point { + int x; + int y; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + +} diff --git "a/src/dami/programmers/level3/review/\354\205\224\355\213\200\353\262\204\354\212\244.java" "b/src/dami/programmers/level3/review/\354\205\224\355\213\200\353\262\204\354\212\244.java" new file mode 100644 index 0000000..2dfae21 --- /dev/null +++ "b/src/dami/programmers/level3/review/\354\205\224\355\213\200\353\262\204\354\212\244.java" @@ -0,0 +1,48 @@ +package dami.programmers.level3.review; + +import java.time.LocalTime; +import java.util.Arrays; + +// https://programmers.co.kr/learn/courses/30/lessons/17678 + +// 1. timetable 정렬 +// 2. 마지막 버스 탑승자 목록 구하기 +// 2-1. 마지막 전 버스들 만큼 탑승자 처리하고 +// 2-2. 마지막 버스 첫 탑승자 인덱스 구하기 +// 3. 마지막 탑승자 번호가 최대인원이면 맨 마지막 탑승자시간보다 -1분 == 콘 도착시간 +// else 버스 시간 == 콘 도착시간 +public class 셔틀버스 { + private static final String FIRST_BUS = "09:00"; + + public String solution(int n, int t, int m, String[] timetable) { + Arrays.sort(timetable); + + LocalTime busTime = LocalTime.parse(FIRST_BUS); + + int firstPersonOfLastBus = 0; + for (int i = 0; i < n - 1 && firstPersonOfLastBus < timetable.length - 1; i++) { + int currentM = m; + while (busTime.toString().compareTo(timetable[firstPersonOfLastBus]) >= 0 && currentM > 0) { + firstPersonOfLastBus++; + currentM--; + } + busTime = busTime.plusMinutes(t); + } + + int lastPersonOfLastBus = firstPersonOfLastBus; + int currentM = m; + while (lastPersonOfLastBus < timetable.length - 1 && busTime.toString().compareTo(timetable[lastPersonOfLastBus]) >= 0 && currentM > 0) { + lastPersonOfLastBus++; + currentM--; + } + + String result; + if (busTime.toString().compareTo(timetable[lastPersonOfLastBus]) >= 0 && lastPersonOfLastBus - firstPersonOfLastBus == m - 1) { + result = LocalTime.parse(timetable[lastPersonOfLastBus]).minusMinutes(1).toString(); + } else { + result = busTime.toString(); + } + return result; + } + +} diff --git "a/src/dami/programmers/level3/review/\354\236\220\353\254\274\354\207\240\354\231\200_\354\227\264\354\207\240.java" "b/src/dami/programmers/level3/review/\354\236\220\353\254\274\354\207\240\354\231\200_\354\227\264\354\207\240.java" new file mode 100644 index 0000000..212b7c4 --- /dev/null +++ "b/src/dami/programmers/level3/review/\354\236\220\353\254\274\354\207\240\354\231\200_\354\227\264\354\207\240.java" @@ -0,0 +1,71 @@ +package dami.programmers.level3.review; + +// https://programmers.co.kr/learn/courses/30/lessons/60059?language=java + +// 1. 자물쇠 왼쪽 상단 모서리부터 오른쪽 하단 모서리 한 칸까지 이동할 수 있는 큰 배열 생성 +// 2. 자물쇠 홈 좌표 목록 기록 +// 3. 키를 왼쪽 상단 모서리 한 칸 위치부터 이동시키면서 자물쇠 전체가 1로 채워졌는지 확인 (구해둔 좌표 목록만 확인) +// 4. 키가 오른쪽 하단 모서리 한 칸 위치까지 돌고 자물쇠 풀리지 않으면 90도 회전 +public class 자물쇠와_열쇠 { + private static final int CHECK_COUNT = 4; // 네 방향 + + public boolean solution(int[][] key, int[][] lock) { + int lockSize = lock.length; + + // 열쇠 이동시킬 큰 판 수식 : 2(keySize - 1) + lock + int bigSize = 2 * (key.length - 1) + lock.length; + int start = bigSize / lockSize; + + int[][] bigArray = new int[bigSize][bigSize]; + for (int i = start; i < start + lockSize ; i++) { + for (int j = start; j < start + lockSize; j++) { + bigArray[i][j] = lock[i - start][j - start]; + } + } + + for (int checkCount = 0; checkCount < CHECK_COUNT; checkCount++) { // 4번 회전 + + for (int i = 0; i <= bigSize - key.length; i++) { // 큰 판에서 key 이동 가능한 만큼 반복 + for (int j = 0; j <= bigSize - key.length; j++) { + if (isOpen(bigArray, start, lockSize, key, i, j)) { + return true; + } + } + } + + key = rotate(key); + } + + return false; + } + + private boolean isOpen(int[][] bigArray, int lockStart, int lockSize, int[][] key, int bigI, int bigJ) { + int[][] openedLock = new int[lockSize][lockSize]; + + for (int i = lockStart; i < lockStart + lockSize; i++) { + for (int j = lockStart; j < lockStart + lockSize; j++) { + openedLock[i - lockStart][j - lockStart] += bigArray[i][j]; + // 자물쇠랑 키 겹치는 범위 + key + if (i - bigI >= 0 && i - bigI < key.length && j - bigJ >= 0 && j - bigJ < key.length) { + openedLock[i - lockStart][j - lockStart] += key[i - bigI][j - bigJ]; + } + + if (openedLock[i - lockStart][j - lockStart] != 1) { + return false; + } + } + } + return true; + } + + private int[][] rotate(int[][] key) { + int length = key.length; + int[][] rotated = new int[length][length]; + for (int i = 0; i < length; i++) { + for (int j = 0; j < length; j++) { + rotated[i][j] = key[length - 1 - j][i]; + } + } + return rotated; + } +} diff --git "a/src/dami/programmers/level3/\353\213\250\354\206\215\354\271\264\353\251\224\353\235\274.java" "b/src/dami/programmers/level3/\353\213\250\354\206\215\354\271\264\353\251\224\353\235\274.java" new file mode 100644 index 0000000..17d6eac --- /dev/null +++ "b/src/dami/programmers/level3/\353\213\250\354\206\215\354\271\264\353\251\224\353\235\274.java" @@ -0,0 +1,22 @@ +package dami.programmers.level3; + +import java.util.Arrays; +import java.util.Comparator; + +public class 단속카메라 { + public int solution(int[][] routes) { + Arrays.sort(routes, Comparator.comparingInt(route -> route[1])); + + int camera = 0; + int point = Integer.MIN_VALUE; + for (int[] route : routes) { + // [i][1] 오름차순으로 정렬을 해주었기 때문에 [i][0] 만 비교해주어도 됨 + if (route[0] > point) { + camera++; + point = route[1]; + } + } + + return camera; + } +} diff --git "a/src/dami/programmers/level3/\354\240\225\354\210\230_\354\202\274\352\260\201\355\230\225.java" "b/src/dami/programmers/level3/\354\240\225\354\210\230_\354\202\274\352\260\201\355\230\225.java" new file mode 100644 index 0000000..6506e65 --- /dev/null +++ "b/src/dami/programmers/level3/\354\240\225\354\210\230_\354\202\274\352\260\201\355\230\225.java" @@ -0,0 +1,61 @@ +package dami.programmers.level3; + + +// 참고 https://codedrive.tistory.com/49 +public class 정수_삼각형 { + private int[][] sums; + + public int solution(int[][] triangle) { + int sum = triangle[0][0]; + if (triangle.length == 1) { + return sum; + } + + sums = triangle; + findMaxSum(1, 0); + + int max = 0; + for (int i = 0; i < sums[triangle.length - 1].length; i++) { + max = Math.max(max, sums[triangle.length - 1][i]); + } + return max; + } + + private void findMaxSum(int row, int col) { + if (row == sums.length - 1 && col == sums[row].length - 1) { + return; + } + + if (col == 0) { + sums[row][col] += sums[row - 1][col]; + findMaxSum(row, col + 1); + return; + } + + if (row == col) { + sums[row][col] += sums[row - 1][col - 1]; + findMaxSum(row + 1, 0); + return; + } + + sums[row][col] += Math.max(sums[row - 1][col], sums[row - 1][col - 1]); + findMaxSum(row, col + 1); + } + +} + + +/* // 다른 풀이 + + public int solution(int[][] triangle) { + for (int i = 1; i < triangle.length; i++) { + triangle[i][0] += triangle[i-1][0]; + triangle[i][i] += triangle[i-1][i-1]; + for (int j = 1; j < i; j++) + triangle[i][j] += Math.max(triangle[i-1][j-1], triangle[i-1][j]); + } + + return Arrays.stream(triangle[triangle.length-1]).max().getAsInt(); + } + +*/ diff --git a/src/dami/programmers/sql/questions.sql b/src/dami/programmers/sql/questions.sql new file mode 100644 index 0000000..c04cd0c --- /dev/null +++ b/src/dami/programmers/sql/questions.sql @@ -0,0 +1,64 @@ +/* 최솟값 구하기 */ +/* https://programmers.co.kr/learn/courses/30/lessons/59038 */ +SELECT MIN(DATETIME) AS '시간' +FROM ANIMAL_INS + +/* 동물 수 구하기 */ +/* https://programmers.co.kr/learn/courses/30/lessons/59406 */ +SELECT COUNT(*) AS count +FROM ANIMAL_INS + +/* 있었는데요 없었습니다 */ +/* https://programmers.co.kr/learn/courses/30/lessons/59043 */ +SELECT ins.ANIMAL_ID, ins.NAME +FROM ANIMAL_INS ins, ANIMAL_OUTS outs +WHERE ins.ANIMAL_ID = outs.ANIMAL_ID +AND ins.DATETIME > outs.DATETIME +ORDER BY ins.DATETIME + +/* 오랜 기간 보호한 동물(1) */ +/* https://programmers.co.kr/learn/courses/30/lessons/59044 */ +/* 1. not in */ +SELECT NAME, DATETIME +FROM ANIMAL_INS +WHERE ANIMAL_ID NOT IN ( SELECT ANIMAL_ID + FROM ANIMAL_OUTS ) +ORDER BY DATETIME +LIMIT 3 + +/* 2. left join */ +SELECT i.NAME, i.DATETIME +FROM ANIMAL_INS i LEFT JOIN ANIMAL_OUTS o USING (ANIMAL_ID) +WHERE o.DATETIME IS NULL +ORDER BY i.DATETIME +LIMIT 3 + +/* 보호소에서 중성화한 동물 */ +/* https://programmers.co.kr/learn/courses/30/lessons/59045 */ +SELECT ins.ANIMAL_ID, ins.ANIMAL_TYPE, ins.NAME +FROM ANIMAL_INS ins, ANIMAL_OUTS outs +WHERE ins.ANIMAL_ID = outs.ANIMAL_ID +AND ins.SEX_UPON_INTAKE REGEXP 'Intact' +AND outs.SEX_UPON_OUTCOME REGEXP 'Spayed|Neutered' + +/* 우유와 요거트가 담긴 장바구니 */ +/* https://programmers.co.kr/learn/courses/30/lessons/62284 */ +/* 1. 내 풀이 -> 항목 늘어날 때마다 서브쿼리도 늘려야하는 문제.. */ +SELECT m.CART_ID +FROM CART_PRODUCTS m, ( + SELECT CART_ID, NAME + FROM CART_PRODUCTS + WHERE NAME = 'Yogurt' +) y +WHERE m.CART_ID = y.CART_ID +AND m.NAME = 'Milk' +GROUP BY CART_ID +ORDER BY CART_ID + +/* 2. 베스트 풀이인듯? */ +SELECT CART_ID +FROM CART_PRODUCTS +WHERE NAME IN ('Milk', 'Yogurt') +GROUP BY CART_ID +HAVING COUNT(DISTINCT NAME) >= 2 +ORDER BY CART_ID diff --git a/src/dami/questions/Line3.java b/src/dami/questions/Line3.java new file mode 100644 index 0000000..b9754e2 --- /dev/null +++ b/src/dami/questions/Line3.java @@ -0,0 +1,46 @@ +package dami.questions; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +// 인덱스, 개수 계산 헷갈렸던 문제 + +// 1. 0의 index값을 가지는 List 생성 +// 2. n이 0의 위치 리스트 크기보다 같거나 크면 road 길이 반환 +// 3. 0의 위치 리스트 맨 앞부터 반복 +// - n개씩 보수한 결과 도로 길이 최대값 계산 +public class Line3 { + public int solution(String road, int n) { + List zeroIndexes = IntStream.range(0, road.length()) + .boxed() + .filter(num -> road.charAt(num) == '0') + .collect(Collectors.toList()); + + int zeroCount = zeroIndexes.size(); + if (zeroCount <= n) { + return road.length(); + } + + // zeroIndexes 앞에부터 n개씩 반복할 때 + // 첫 턴 : start = 0, end = zi[i + n] + // 둘째 턴 ~ 마지막 전 턴 : start = zi[i - 1] + 1, end = zi[i + n] + // 마지막 턴 : start = zi[i - 1] + 1, end = road.length() - 1 + // 가 되기 때문에 zeroIndexes list에 추가 + // 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1 1 1 1 1 0 0 0 1 1 1 1 1 + // -1 0 1 2 3 4 5 6 7 8 9 . . . 14. . . . . . . 29 + zeroIndexes.add(0, -1); + zeroIndexes.add(road.length() - 1); + + int max = 0; + // 0의 인덱스 리스트 총 개수만큼(zeroCount)에서 마지막 n개가 될 수 있는 i까지만 반복 + // ex. n=3일 때, zi = {3, 8, 9, 15, 22, 23, 24}에서 22(=zi[4])까지만 반복 + for (int i = 1; i <= zeroCount - n; i++) { + int start = zeroIndexes.get(i - 1) + 1; + int end = zeroIndexes.get(i + n); + int length = end - start; + max = Math.max(length, max); + } + return max; + } +} diff --git a/src/dami/questions/Line6.java b/src/dami/questions/Line6.java new file mode 100644 index 0000000..02036c2 --- /dev/null +++ b/src/dami/questions/Line6.java @@ -0,0 +1,79 @@ +package dami.questions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +// Array를 List로 변환할 때 List list = Arrays.asList(array); 하면 불변 List(unmodifiable)가 되어 수정 불가 +// => 수정 시, UnsupportedOperationException 발생 +// 따라서 아래 방법 중 하나로 생성 +// 1. List 생성 후 addAll +// => reference가 그대로 전달 +// 2. new ArrayList<>(Arrays.asList(array)); +// => copy이기 때문에 reference는 없어지지만 불필요하게 두 개 생성 + +public class Line6 { + public String[] solution(String[] directory, String[] commands) { + Directories directories = Directories.of(directory); + + for (String command : commands) { + directories.executeCommand(command); + } + + return directories.asArray(); + } +} + +class Directories { + private final List directories; + + public Directories(List directories) { + this.directories = new ArrayList<>(); + this.directories.addAll(directories); + } + + public static Directories of(String[] directories) { + return new Directories(Arrays.asList(directories)); + } + + public String[] asArray() { + return directories.toArray(new String[0]); + } + + public void executeCommand(String command) { + String[] splitCommand = command.split(" "); + + if (command.contains("mkdir")) { + mkdir(splitCommand[1]); + return; + } + + if (command.contains("cp")) { + cp(splitCommand[1], splitCommand[2].equals("/") ? "" : splitCommand[2]); + return; + } + + if (command.contains("rm")) { + rm(splitCommand[1]); + } + } + + private void mkdir(String newDirectory) { + directories.add(newDirectory); + } + + private void cp(String source, String destination) { + int lastIndex = source.lastIndexOf("/"); + directories.addAll( + directories.stream() + .filter(dir -> dir.startsWith(source)) + .map(dir -> destination + dir.substring(lastIndex)) + .collect(Collectors.toList()) + ); + } + + private void rm(String rmDirectory) { + directories.removeIf(dir -> dir.startsWith(rmDirectory)); + } +} diff --git a/src/dami/questions/Questions.java b/src/dami/questions/Questions.java new file mode 100644 index 0000000..ca35610 --- /dev/null +++ b/src/dami/questions/Questions.java @@ -0,0 +1,37 @@ +package dami.questions; + +public class Questions { + public void solutions() { + //new Task1().solution(6, 2, new char[] {'B', 'C'}, 2, new int[] {3, -2}); + //new Task1().solution(17, 5, new char[] {'B', 'D', 'I', 'M', 'P'}, 11, new int[] {3,-4,5,6,-7,-8,10,-12,-15,-20,23}); + + //new Task2().solution(2, 6, new int[][] {{6, 2, 11, 0, 3, 5}, {6, 3, 0, 9, 0, 5}}); + //new Task2().solution(3, 10, new int[][] {{6, 12, 0, 2, 8, 4, 0, 7, 3, 6}, {6, 1,3,0,2,8,0,0,13,8}, {6,3,0,10,6,5,7,0,0,3}}); + + //new Task3().solution(2, new String[] {"B2(RG)", "3(R2(GB))"}); + //new Task3().solution(3, new String[] {"3(BR2(R))", "B(RGB(RG))", "1B2R3G"}); + + + // 001100, 3 / 001100, 5 + //new Line3().solution("111011110011111011111100011111", 3); + /* + System.out.println(Arrays.toString(new Line6().solution( + new String[]{"/", "/hello", "/hello/tmp", "/root", "/root/abcd", "/root/abcd/etc", "/root/abcd/hello"} + , new String[]{"mkdir /root/tmp", "cp /hello /root/tmp", "rm /hello"} + ))); + System.out.println(Arrays.toString(new Line6().solution( + new String[]{"/"} + , new String[]{"mkdir /a", "mkdir /a/b", "mkdir /a/b/c", "cp /a/b /", "rm /a/b/c"} + ))); + */ + + //new Task6().solution("ZNMD"); + + //new Task7().solution(17, 5, new char[] {'B', 'D', 'I', 'M', 'P'}, 11, new int[] {3, -4, 5, 6, -7, -8, 10, -12, -15, -20, 23}); + //new Task8().solution(2, 6, new int[][] {{6,2,11,0,3,5},{6,3,0,9,0,5}}); + //new Task8().solution(3, 10, new int[][] {{6,12,0,2,8,4,0,7,3,6},{6,1,3,0,2,8,0,0,13,8}, {6,3,0,10,6,5,7,0,0,3}}); + //new Task9().solution(2, new String[]{"B2(RG)", "3(R2(GB))"}); + new Task10().solution(6, new int[][]{{0,1,1,0,0,0},{0,1,1,0,1,1}, {0,0,0,0,1,1}, {0,0,0,0,1,1}, {1,1,0,0,1,0}, {1,1,1,0,0,0}}); + new Task10().solution(4, new int[][]{{1,0,0,0},{1,0,0,0}, {0,0,0,0}, {0,0,1,1}}); + } +} diff --git a/src/dami/questions/Task1.java b/src/dami/questions/Task1.java new file mode 100644 index 0000000..171e4e2 --- /dev/null +++ b/src/dami/questions/Task1.java @@ -0,0 +1,80 @@ +package dami.questions; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.IntStream; + +public class Task1 { + private Map taggerCounts; + private Participants participants; + + public void solution(int numOfAllPlayers, int numOfQuickPlayers, char[] namesOfQuickPlayers, int numOfGames, int[] numOfMovesPerGame) { + initGame(numOfAllPlayers); + char tagger = 'A'; + int taggerPos = 0; + + for (int i = 0; i < numOfGames; i++) { + // (현재 술래 위치 + 이동 칸수) % 앉아있는 참여자 수 + taggerPos = (taggerPos + numOfMovesPerGame[i]) % (numOfAllPlayers - 1); + if (taggerPos < 0) { + taggerPos += (numOfAllPlayers - 1); + } + + taggerCounts.put(tagger, taggerCounts.get(tagger) + 1); + if (!participants.isFaster(taggerPos, namesOfQuickPlayers)) { + tagger = participants.changeTagger(taggerPos, tagger); + } + } + taggerCounts.put(tagger, taggerCounts.get(tagger) + 1); + + printGame(); + } + + private void initGame(int numOfAllPlayers) { + participants = new Participants(numOfAllPlayers); + taggerCounts = new HashMap<>(); + for (int i = 0; i < participants.size(); i++) { + taggerCounts.put(participants.getName(i), 0); + } + taggerCounts.put('A', 0); + } + + private void printGame() { + for (int i = 0; i < participants.size(); i++) { + System.out.println(participants.getName(i) + " " + taggerCounts.get(participants.getName(i))); + taggerCounts.remove(participants.getName(i)); + } + taggerCounts.forEach((key, value) -> System.out.println(key + " " + value)); + } +} + +class Participants { + private final char[] names; + + public Participants(int num) { + names = new char[num - 1]; + for (int i = 0; i < num - 1; i++) { + names[i] = (char)('B' + i); + } + } + + public char getName(int index) { + return names[index]; + } + + public int size() { + return names.length; + } + + public boolean isFaster(int index, char[] names) { + return IntStream.range(0, names.length) + .mapToObj(i -> names[i]) + .anyMatch(name -> name == this.names[index]); + } + + public char changeTagger(int index, char tagger) { + char temp = names[index]; + names[index] = tagger; + return temp; + } +} diff --git a/src/dami/questions/Task2.java b/src/dami/questions/Task2.java new file mode 100644 index 0000000..a5fb8e0 --- /dev/null +++ b/src/dami/questions/Task2.java @@ -0,0 +1,48 @@ +package dami.questions; + +import java.util.Arrays; + +// 완 +// 백준 '빗물' 문제와 유사 +public class Task2 { + public void solution(int day, int width, int[][] blocks) { // 작업일, 너비, 공사 기간 동안 쌓을 벽돌 개수 + int[] workResult = new int[width]; + int cement = 0; + for (int i = 0; i < day; i++) { + // 다음날 벽돌 추가 + for (int j = 0; j < width; j++) { + workResult[j] += blocks[i][j]; + } + + int left = 0, right = width - 1; + while (canWork(workResult)) { + // 시멘트 작업 가능 범위 확인 + while (workResult[left] <= 0) { + left++; + } + while (workResult[right] <= 0) { + right--; + } + int min = Math.min(workResult[left], workResult[right]); + + for (int j = 0; j < width; j++) { + // 시멘트 작업 가능 범위 내에만 시멘트 추가 + if (j >= left && j <= right && workResult[j] < min) { + cement += min - workResult[j]; + workResult[j] += min - workResult[j]; + } + workResult[j] -= min; + } + } + } + + System.out.println(cement); + } + + // 시멘트가 넘치지 않도록 양쪽 사이드 벽이 될 수 있는지 판단 + private boolean canWork(int[] blocks) { + return Arrays.stream(blocks) + .filter(block -> block > 0) + .count() >= 2; + } +} diff --git a/src/dami/questions/Task3.java b/src/dami/questions/Task3.java new file mode 100644 index 0000000..6d29731 --- /dev/null +++ b/src/dami/questions/Task3.java @@ -0,0 +1,67 @@ +package dami.questions; + +import java.util.Stack; + +public class Task3 { + public void solution(int numOfOrder, String[] orderArr) { + for (int i = 0; i < numOfOrder; i++) { + StringBuilder result = new StringBuilder(); + Stack orderStack = new Stack<>(); + char[] order = orderArr[i].toCharArray(); + + for (char c : order) { + if (c == ')') { + while (!orderStack.isEmpty() && !"(".equals(orderStack.peek())) { + result.append(orderStack.pop()); + } + if ("(".equals(orderStack.pop())) { + orderStack.push(appendBy(orderStack.pop(), result)); + } + continue; + } + + if (c != '(' && !orderStack.isEmpty() && isNumber(orderStack.peek())) { + orderStack.push(appendBy(orderStack.pop(), new StringBuilder(String.valueOf(c)))); + continue; + } + + orderStack.push(String.valueOf(c)); + } + + while (!orderStack.isEmpty()) { + result.append(orderStack.pop()); + } + + System.out.println(result.reverse()); + } + } + + private boolean isNumber(String prefix) { + return prefix.charAt(0) >= '1' && prefix.charAt(0) <= '9'; + } + + private String appendBy(String prefix, StringBuilder result) { + if (isNumber(prefix)) { + return appendNumber((prefix.charAt(0) - '0'), result); + } + return appendCharacter(prefix, result); + } + + private String appendNumber(int number, StringBuilder string) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < number; i++) { + sb.append(string); + } + string.delete(0, string.length()); + return sb.toString(); + } + + private String appendCharacter(String prefix, StringBuilder string) { + StringBuilder sb = new StringBuilder(string); + for (int i = 0; i < sb.length(); i+=2) { + sb.insert(i+1, prefix); + } + string.delete(0, string.length()); + return sb.toString(); + } +} diff --git a/src/dami/questions/Task4.java b/src/dami/questions/Task4.java new file mode 100644 index 0000000..52340e5 --- /dev/null +++ b/src/dami/questions/Task4.java @@ -0,0 +1,11 @@ +package dami.questions; + +public class Task4 { + public int solution(int N) { + int digit = (int) Math.log10(N); + if (digit == 0) { + return 0; + } + return (int) Math.pow(10, digit); + } +} diff --git a/src/dami/questions/Task5.java b/src/dami/questions/Task5.java new file mode 100644 index 0000000..40f1e20 --- /dev/null +++ b/src/dami/questions/Task5.java @@ -0,0 +1,27 @@ +package dami.questions; + +// 참고 : https://github.com/geektimus/java-challenges/blob/master/src/main/java/com/codingmaniacs/codility/NumericChallenges.java +public class Task5 { + public int solution(int N, int K) { + if (K == 0) { + return N - 1; + } + + int minPlays = 0; + + while (N > 1 && K > 0) { + if (N % 2 == 0) { + K--; + N /= 2; + } else { + N--; + } + minPlays++; + } + + if (N > 1) { + minPlays += N - 1; + } + return minPlays; + } +} diff --git a/src/delf/backjoon/Q4963.java b/src/delf/backjoon/Q4963.java new file mode 100644 index 0000000..c8e014e --- /dev/null +++ b/src/delf/backjoon/Q4963.java @@ -0,0 +1,68 @@ +package backjoon; + +import java.util.Scanner; + +public class Q4963 { + + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + Q4963 q4963 = new Q4963(); + int n, m; + do { + + n = scanner.nextInt(); + m = scanner.nextInt(); + int[][] map = new int[m][n]; // 4 5 + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + map[i][j] = scanner.nextInt(); + } + } + + if (n == 0 && m == 0) { + break; + } + + System.out.println(q4963.solution(n, m, map)); + + } while (true); + } + + private final static int[][] DIRECTION = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; + + public int solution(int n, int m, int[][] map) { + int cnt = 0; + boolean[][] isVisit = new boolean[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (isVisit[i][j] || map[i][j] == 0) { + continue; + } + cnt += dfs(i, j, map, isVisit); + } + } + return cnt; + } + private int dfs(int n, int m, int[][] map, boolean[][] isVisit) { + isVisit[m][n] = true; + + for (int[] dir : DIRECTION) { + int nextN = n + dir[1]; + int nextM = m + dir[0]; + + if (nextN < 0 || nextM < 0 || nextN >= map[0].length || nextM >= map.length) { + continue; + } + + if (isVisit[nextM][nextN] || map[nextM][nextN] == 0) { + continue; + } + + dfs(nextN, nextM, map, isVisit); + } + + return 1; + } +} diff --git a/src/delf/dailyprogramming/CT116.java b/src/delf/dailyprogramming/CT116.java new file mode 100644 index 0000000..7b8fdd7 --- /dev/null +++ b/src/delf/dailyprogramming/CT116.java @@ -0,0 +1,49 @@ +package dailyprogramming; + +import java.util.Arrays; + +/* + * 빗물 담기 문제(Trapping Rain Water Problem)입니다. + * + * 너비가 1인 막대기들이 서 있고, 그 길이가 배열로 주어집니다. + * 여기에 비가 내려 물이 고인다고 할 때, 담기는 물의 최대 양을 구하시오. + * + * Input: [7, 0, 4, 2, 5, 0, 6, 4, 0, 5] + * Output: 25 + */ +@SuppressWarnings("Duplicates") +public class CT116 { + public static void main(String[] args) { + System.out.println(new CT116().solution(new int[]{7, 0, 4, 2, 5, 0, 6, 4, 0, 5})); + } + + public int solution(int[] sticks) { + int waterVolume = 0; + int maxHeight = 0; + int maxIndex = 0; + for (int i = 0; i < sticks.length; i++) { + if (sticks[i] > maxHeight) { // 벽 찾아 + for (int j = maxIndex + 1; j < i; j++) { // 물 채워 + waterVolume += (maxHeight - sticks[j]); + sticks[j] = maxHeight; + } + maxHeight = sticks[i]; + maxIndex = i; + } + } + + maxHeight = 0; + maxIndex = 0; + for (int i = sticks.length - 1; i >= 0; i--) { + if (sticks[i] > maxHeight) { + for (int j = maxIndex - 1; j > i; j--) { + waterVolume += (maxHeight - sticks[j]); + sticks[j] = maxHeight; + } + maxHeight = sticks[i]; + maxIndex = i; + } + } + return waterVolume; + } +} diff --git a/src/delf/etc/NV01.java b/src/delf/etc/NV01.java new file mode 100644 index 0000000..7e34dc9 --- /dev/null +++ b/src/delf/etc/NV01.java @@ -0,0 +1,169 @@ +package etc; + +import java.util.*; + +public class NV01 { + + public static void main(String[] args) throws CloneNotSupportedException { + System.out.println(Arrays.toString(new NV01().solution( + new String[]{"/", "/hello", "/hello/tmp", "/root", "/root/abcd", "/root/abcd/etc", "/root/abcd/hello"}, + new String[]{"mkdir /root/tmp", "cp /hello /root/tmp", "rm /hello"})) + ); + + System.out.println(Arrays.toString(new NV01().solution( + new String[]{"/"}, + new String[]{"mkdir /a", "mkdir /a/b", "mkdir /a/b/c", "cp /a/b /", "rm /a/b/c"})) + ); + + System.out.println(Arrays.toString(new NV01().solution( + new String[]{"/"}, + new String[]{"mkdir /a", "mkdir /a/b", "mkdir /a/b/c", "cp /a/b /", "rm /a/b/c"})) + ); + } + + public String[] solution(String[] directory, String[] command) throws CloneNotSupportedException { + /* (인자로 받은) 초기 디렉토리 생성 */ + Directory root = new Directory(null, directory[0]); // 루트 생성 + for (int i = 1; i < directory.length; i++) { + mkdir(root, directory[i]); + } + + /* 명령 수행 */ + for (String cmd : command) { + String[] arg = cmd.split(" "); + switch (arg[0]) { // 명령어 + case "mkdir": + mkdir(root, arg[1]); + break; + case "cp": + cp(root, arg[1], arg[2]); + break; + case "rm": + rm(root, arg[1]); + break; + } + } + + /* 출력 */ + return root.tree(new ArrayList<>()).stream() + .sorted(String::compareTo) + .toArray(String[]::new); + } + + public void mkdir(Directory root, String path) { + String[] pathElements = path.split("/"); + + String[] onlyPath = Arrays.copyOfRange(pathElements, 1, pathElements.length - 1); // 경로만 추출 + Directory dir = (Directory) root.open(onlyPath); // 해당 경로의 디렉토리 + + String name = pathElements[pathElements.length - 1]; // 생성 디렉토리 이름 추출 + dir.add(new Directory(dir, name)); // 디렉토리 생성 및 추가 + } + + public void cp(Directory root, String sourcePath, String destPath) throws CloneNotSupportedException { + String[] onlyPath = getPath(sourcePath); + Directory sourceDir = (Directory) root.open(onlyPath); // src 디렉토리 가져오기 + + onlyPath = getPath(destPath); + Directory destDir = (Directory) root.open(onlyPath); // dest 디렉토리 가져오기 + + Directory copied = (Directory) sourceDir.clone(); // 복사 + destDir.add(copied); // 추가 + } + + public void rm(Directory root, String path) { + String[] onlyPath = getPath(path); + Directory sourceDir = (Directory) root.open(onlyPath); // 삭제할 디렉토리 가져오기 + sourceDir.remove(); + } + + private String[] getPath(String path) { // 매핑 + String[] pathElements = path.split("/"); + if (pathElements.length == 0) { + return new String[]{}; + } + return Arrays.copyOfRange(pathElements, 1, pathElements.length); + } + + + class Directory extends File { + public Directory(File parent, String name) { + super(parent, name); + } + + private Map list; // 하위 디렉토리(파일) + + public void add(File file) { // 디렉토리(파일) 추가 + if (Objects.isNull(list)) { + list = new HashMap<>(); + } + file.parent = this; + list.put(file.name, file); + } + + public File remove() { + return remove(this); + } + + public File remove(File file) { + return ((Directory) this.parent).list.remove(file.name); // 자신의 부모의 list에서 자신을 삭제 + } + + public File open(String[] path) { + return open(path, 0); // depth: 들어간 깊이 + } + + private File open(String[] path, int depth) { + if (depth == path.length) { // 목적지 도달 + return this; + } + // 다음 디렉토리 찾아서 열기 반복 + String name = path[depth]; + Directory nextDir = (Directory) list.get(name); + return nextDir.open(path, depth + 1); + } + + public List tree(List result) { // 배열의 형태로 출력하기 위해 List받음 + result.add(this.toString()); // dfs 하면서 추가 (toString() 오버라이드) + if (Objects.isNull(list) || list.isEmpty()) { + return result; + } + + for (String name : list.keySet()) { + ((Directory) list.get(name)).tree(result); + } + return result; + } + + @Override + protected Object clone() { // 깊은 복사를 위한 오버라이딩 + Directory dir = new Directory(this.parent, this.name); + dir.list = new HashMap<>(); + for (String s : list.keySet()) { + dir.list.put(s, new Directory(dir, s)); + } + return dir; + } + } + + class File { + protected String name; + protected File parent; + + public File(File parent, String name) { + this.parent = parent; + this.name = name; + } + + @Override + public String toString() { + if (parent == null) { + return name; + } + if (parent.parent == null) { + return "/" + name; + } + return parent + "/" + name; + } + } +} diff --git a/src/delf/etc/appdevmatching2020/Solution.java b/src/delf/etc/appdevmatching2020/Solution.java new file mode 100644 index 0000000..74d3067 --- /dev/null +++ b/src/delf/etc/appdevmatching2020/Solution.java @@ -0,0 +1,22 @@ +package etc.appdevmatching2020; + + +import java.util.*; +import java.util.stream.Collectors; + +public class Solution { + public int solution(long n) { + long tmp = n; + int cnt = 0; + Set set = new HashSet<>(); + do { + long div = n % 10; + if (div != 0 && !set.contains(div) && tmp % (div) == 0) { + cnt++; + } + set.add(div); + } while ((n /= 10) > 0); + + return cnt; + } +} diff --git a/src/delf/etc/devmatching2021/Solution1.java b/src/delf/etc/devmatching2021/Solution1.java new file mode 100644 index 0000000..df6ee8e --- /dev/null +++ b/src/delf/etc/devmatching2021/Solution1.java @@ -0,0 +1,30 @@ +package etc.devmatching2021; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class Solution1 { + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution1().solution(new int[]{44, 1, 0, 0, 31, 25}, new int[]{31, 10, 45, 1, 6, 19}))); + System.out.println(Arrays.toString(new Solution1().solution(new int[]{0, 0, 0, 0, 0, 0}, new int[]{38, 19, 20, 40, 15, 25}))); + System.out.println(Arrays.toString(new Solution1().solution(new int[]{45, 4, 35, 20, 3, 9}, new int[]{20, 9, 3, 45, 4, 35}))); + } + + private static final int[] WIN = new int[]{6, 6, 5, 4, 3, 2, 1}; + + public int[] solution(int[] lottos, int[] winNums) { + Set set = new HashSet<>(); + for (int winNum : winNums) { + set.add(winNum); + } + int empty = 0; + for (Integer lotto : lottos) { + if (lotto == 0) { + empty++; + } + set.remove(lotto); + } + return new int[]{WIN[6 - set.size() + empty], WIN[6 - set.size()]}; + } +} diff --git a/src/delf/etc/devmatching2021/Solution2.java b/src/delf/etc/devmatching2021/Solution2.java new file mode 100644 index 0000000..b511b08 --- /dev/null +++ b/src/delf/etc/devmatching2021/Solution2.java @@ -0,0 +1,62 @@ +package etc.devmatching2021; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Solution2 { + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution2().solution(6, 6, new int[][]{{2, 2, 5, 4}, {3, 3, 6, 6}, {5, 1, 6, 3}}))); + System.out.println(Arrays.toString(new Solution2().solution(3, 3, new int[][]{{1, 1, 2, 2}, {1, 2, 2, 3}, {2, 1, 3, 2}, {2, 2, 3, 3}}))); + System.out.println(Arrays.toString(new Solution2().solution(100, 97, new int[][]{{1, 1, 100, 97}}))); + } + + public int[] solution(int rows, int columns, int[][] queries) { + int[][] map = new int[rows + 1][columns + 1]; + for (int i = 1; i < map.length; i++) { + for (int j = 1; j < map[i].length; j++) { + map[i][j] = (i - 1) * (map[i].length - 1) + j; + } + } + List answer = new ArrayList<>(); + for (int[] query : queries) { + map = rotate(map, query, answer); + } + + return answer.stream().mapToInt(i -> i).toArray(); + } + + private int[][] rotate(int[][] map, int[] query, List answer) { + int[][] arr = new int[map.length][map[0].length]; + for (int i = 0; i < arr.length; i++) { + System.arraycopy(map[i], 0, arr[i], 0, arr[i].length); + } + + int startRow = query[0]; + int endRow = query[2]; + int startCol = query[1]; + int endCol = query[3]; + + int min = Integer.MAX_VALUE; + for (int r = startRow; r <= endRow; r++) { + for (int c = startCol; c <= endCol; c++) { + if (r != startRow && r != endRow && c != startCol && c != endCol) { + continue; + } + if (r == startRow && c != endCol) { + arr[r][c + 1] = map[r][c]; + } else if (r != endRow && c == endCol) { + arr[r + 1][c] = map[r][c]; + } else if (r == endRow && c != startCol) { + arr[r][c - 1] = map[r][c]; + } else if (r != startRow && c == startCol) { + arr[r - 1][c] = map[r][c]; + } + + min = Math.min(min, map[r][c]); + } + } + answer.add(min); + return arr; + } +} diff --git a/src/delf/etc/karecoint2020/Solution01.java b/src/delf/etc/karecoint2020/Solution01.java new file mode 100644 index 0000000..3526034 --- /dev/null +++ b/src/delf/etc/karecoint2020/Solution01.java @@ -0,0 +1,26 @@ +package etc.karecoint2020; + +public class Solution01 { + public static void main(String[] args) { + System.out.println(new Solution01().solution(2, 2)); + + } + + public int solution(int m, int w) { + return simplePermutation(m + w, 3) - ((simplePermutation(m, 3) + simplePermutation(w, 3))); + } + + private int simplePermutation(int n, int r) { + long m = 1; + for (int i = n; i > n - r; i--) { + m *= i; + } + System.out.println("m = " + m); + long s = 1; + for (int i = r; i > 0; i--) { + s *= i; + } + System.out.println("s = " + s); + return (int) (m / s); + } +} \ No newline at end of file diff --git a/src/delf/etc/nhn/NHN2020_01.java b/src/delf/etc/nhn/NHN2020_01.java new file mode 100644 index 0000000..1009add --- /dev/null +++ b/src/delf/etc/nhn/NHN2020_01.java @@ -0,0 +1,62 @@ +package etc.nhn; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class NHN2020_01 { + + public static void main(String[] args) { +// new NHN2020_01().solution(6, new char[]{'B', 'C'}, new int[]{3, -2}); + new NHN2020_01().solution(17, new char[]{'B', 'D', 'I', 'M', 'P'}, new int[]{3, -4, 5, 6, -7, -8, 10, -12, -15, -20, 23}); + } + + public void solution(int numOfAllPlayers, char[] namesOfQuickPlayers, int[] numOfMovesPerGame) { + /* 세팅 */ + List playerInCircle = new ArrayList<>(); // 둘러 앉은 플레이어 List + Map counter = new HashMap<>(); // 술래 카운터 Map + for (int i = 0; i < numOfAllPlayers - 1; i++) { + playerInCircle.add((char) ('B' + i)); // 앉은 플레이어 세팅 (A제외) + } + + int towelPosition = 0; // 수건의 위치(= 술래가 수건을 놓은 위치 = 술래의 출발 위치) + char taggerThisRound = 'A'; // 현 라운드 술래 + counter.merge(taggerThisRound, 1, Integer::sum); // 초기 술래 카운팅 + + /* 라운드만큼 시뮬레이팅 */ + for (int move : numOfMovesPerGame) { + /* 수건을 놓은 위치(= 다음 술래 후보) 계산 */ + towelPosition = nextTargetPosition(numOfAllPlayers - 1, towelPosition, move); + char target = playerInCircle.remove(towelPosition); + + /* 다음 술래와 생존자 계산 */ + char nextTagger = witchIsTagger(taggerThisRound, target, namesOfQuickPlayers); + char survivor = (nextTagger == taggerThisRound) ? target : taggerThisRound; + playerInCircle.add(towelPosition, survivor); // 리스트 정리 + + counter.merge(nextTagger, 1, Integer::sum); // 술래 카운팅 + taggerThisRound = nextTagger; // 다음 라운드 술래 지정 + } + + /* 출력 */ + for (char ch : playerInCircle) { + System.out.println(String.format("%c %d", ch, counter.getOrDefault(ch, 0))); + } + System.out.println(String.format("%c %d", taggerThisRound, counter.getOrDefault(taggerThisRound, 0))); + } + + private int nextTargetPosition(int numOfCirclePlayer, int startIdx, int move) { + int result = startIdx + move; + return result < 0 ? (result + numOfCirclePlayer) % numOfCirclePlayer : result % numOfCirclePlayer; + } + + private char witchIsTagger(char tagger, char target, char[] namesOfQuickPlayers) { + for (char ch : namesOfQuickPlayers) { + if (ch == target) { + return tagger; + } + } + return target; + } +} diff --git a/src/delf/etc/nhn/NHN2020_02.java b/src/delf/etc/nhn/NHN2020_02.java new file mode 100644 index 0000000..5fe123c --- /dev/null +++ b/src/delf/etc/nhn/NHN2020_02.java @@ -0,0 +1,51 @@ +package etc.nhn; + +/** + * @author delf + */ +public class NHN2020_02 { + public static void main(String[] args) { +// System.out.println(new NHN2020_02().solution(6, new int[][]{{6, 2, 11, 0, 3, 5}, {6, 3, 0, 9, 0, 5}})); + System.out.println(new NHN2020_02().solution(10, new int[][]{{6, 12, 0, 2, 8, 4, 0, 7, 3, 6}, {6, 1, 3, 0, 2, 8, 0, 0, 13, 8}, {6, 3, 0, 10, 6, 5, 7, 0, 0, 3}})); + } + + public int solution(int width, int[][] blocks) { + int[] ground = new int[width]; + + int cement = 0; + for (int[] block : blocks) { + /* 쌓기 */ + for (int i = 0; i < ground.length; i++) { + ground[i] += block[i]; + } + + /* 붓고 계산하기 */ + int maxHeight = 0; + int maxIndex = 0; + for (int i = 0; i < ground.length; i++) { + if (ground[i] > maxHeight) { // 벽 찾아 + for (int j = maxIndex + 1; j < i; j++) { // 물 채워 + cement += (maxHeight - ground[j]); + ground[j] = maxHeight; + } + maxHeight = ground[i]; + maxIndex = i; + } + } + + maxHeight = 0; + maxIndex = 0; + for (int i = ground.length - 1; i >= 0; i--) { + if (ground[i] > maxHeight) { + for (int j = maxIndex - 1; j > i; j--) { + cement += (maxHeight - ground[j]); + ground[j] = maxHeight; + } + maxHeight = ground[i]; + maxIndex = i; + } + } + } + return cement; + } +} diff --git a/src/delf/etc/nhn/NHN2020_03.java b/src/delf/etc/nhn/NHN2020_03.java new file mode 100644 index 0000000..32dfacd --- /dev/null +++ b/src/delf/etc/nhn/NHN2020_03.java @@ -0,0 +1,62 @@ +package etc.nhn; + +import java.util.Stack; + +public class NHN2020_03 { + public static void main(String[] args) { + + System.out.println(new NHN2020_03().solution("3(RGBGB)")); + System.out.println(new NHN2020_03().solution("R2(G)B")); + System.out.println(new NHN2020_03().solution("2(B(1(R)2(G2B)))")); + System.out.println(new NHN2020_03().solution("2(B(R)2(G))1(B2(B(R)))")); + // 기본적으론 최근거 pop 해서 앞에 insert + // 닫힌괄호면 String 추가해서 push + // 열린괄호면 그 앞에 문자와 (최근 pop 계산) + pop 해서 다시 push + } + + public String solution(String order) { + Stack stack = new Stack<>(); + for (int i = order.length() - 1; i >= 0; i--) { + char ch = order.charAt(i); + if (ch == ')') { + stack.push(""); + continue; + } + + if (ch == '(') { + String inBracket = stack.isEmpty() ? "" : stack.pop(); + String postBracket = stack.isEmpty() ? "" : stack.pop(); + stack.push(calc(order.charAt(--i), inBracket) + postBracket); + continue; + } + + String pre = Character.isDigit(ch) + ? (ch + calc(ch - '0' - 1, order.charAt(i + 1) + "")) + : ch + ""; + + stack.push(pre + (stack.isEmpty() ? "" : stack.pop())); + } + + return stack.pop(); + } + + private String calc(int num, String ch) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < num; i++) { + result.append(ch); + } + return result.toString(); + } + + private String calc(char preBracket, String inBracket) { + if (Character.isDigit(preBracket)) { + return calc(preBracket - '0', inBracket); + } + StringBuilder result = new StringBuilder(); + for (char ch : inBracket.toCharArray()) { + result.append(preBracket).append(ch); + } + return result.toString(); + } + +} diff --git a/src/delf/hackerrank/ATaleofTwoStacks.java b/src/delf/hackerrank/ATaleofTwoStacks.java new file mode 100644 index 0000000..df79420 --- /dev/null +++ b/src/delf/hackerrank/ATaleofTwoStacks.java @@ -0,0 +1,29 @@ +package hackerrank; + +import java.util.Arrays; +import java.util.LinkedList; + +public class ATaleofTwoStacks { + public static void main(String[] args) { + + Arrays.sort(new long[0]); + } + class MyQueue { + + private LinkedList list = new LinkedList<>(); + + void enqueue(T e) { + list.add(e); + } + + T dequeue() { + return list.removeFirst(); + } + + T peek() { + return list.getLast(); + } + } + + +} diff --git a/src/delf/hackerrank/Abbreviation.java b/src/delf/hackerrank/Abbreviation.java new file mode 100644 index 0000000..87fadf1 --- /dev/null +++ b/src/delf/hackerrank/Abbreviation.java @@ -0,0 +1,33 @@ +package hackerrank; + +/** + * Abbreviation + * https://www.hackerrank.com/challenges/abbreviation/problem + */ +public class Abbreviation { + public static void main(String[] args) { + System.out.println(abbreviation("daBcd", "ABC")); + System.out.println(abbreviation("AfPZN", "APZNC")); + } + + static String abbreviation(String a, String b) { + boolean[][] dp = new boolean[a.length() + 1][b.length() + 1]; + dp[0][0] = true; + + for (int i = 1; i < a.length() + 1; i++) { + for (int j = 0; j < b.length() + 1; j++) { + char aa = a.charAt(i - 1); + if (j > 0 && dp[i - 1][j - 1]) { + char bb = b.charAt(j - 1); + if (aa == bb || Character.toUpperCase(aa) == bb) { + dp[i][j] = true; + } + } + if (Character.isLowerCase(aa) && dp[i - 1][j]) { + dp[i][j] = true; + } + } + } + return dp[a.length()][b.length()] ? "YES" : "NO"; + } +} diff --git a/src/delf/hackerrank/BalancedBrackets.java b/src/delf/hackerrank/BalancedBrackets.java new file mode 100644 index 0000000..6678481 --- /dev/null +++ b/src/delf/hackerrank/BalancedBrackets.java @@ -0,0 +1,48 @@ +package hackerrank; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + + +/** + * Balanced Brackets + * https://www.hackerrank.com/challenges/balanced-brackets/problem + */ +public class BalancedBrackets { + + static Map pair = new HashMap<>(); + + static { + pair.put('(', ')'); + pair.put('{', '}'); + pair.put('[', ']'); + } + + static String isBalanced(String s) { + Stack stack = new Stack<>(); + + for (char ch : s.toCharArray()) { + if (ch == ')' || ch == '}' || ch == ']') { + if (stack.isEmpty()) { + return "NO"; + } + char peek = stack.peek(); + if (pair.get(peek) == ch) { + stack.pop(); + } else { + return "NO"; + } + } else { + stack.add(ch); + } + } + + return stack.isEmpty() ? "YES" : "NO"; + } + + public static void main(String[] args) { + System.out.println(isBalanced("{{[[(())]]}}")); + System.out.println(isBalanced("{[(])}")); + } +} diff --git a/src/delf/hackerrank/Candies.java b/src/delf/hackerrank/Candies.java new file mode 100644 index 0000000..8eb22e0 --- /dev/null +++ b/src/delf/hackerrank/Candies.java @@ -0,0 +1,47 @@ +package hackerrank; + +/** + * Abbreviation + * https://www.hackerrank.com/challenges/abbreviation/problem + */ +public class Candies { + public static void main(String[] args) { + int[] arr = new int[]{10, 2, 4, 2, 6, 1, 7, 8, 9, 2, 1}; + System.out.println(candies(arr.length, arr)); + } + + static long candies(int n, int[] arr) { + + int[] up = new int[arr.length]; + int[] down = new int[arr.length]; + + up[0] = 1; + down[arr.length - 1] = 1; + + for (int i = 1; i < arr.length; i++) { + if (arr[i - 1] < arr[i]) { + up[i] = up[i - 1] + 1; + } else { + up[i] = 1; + } + } + + for (int i = arr.length - 2; i >= 0; i--) { + int t = (arr[i + 1] < arr[i]) ? (down[i + 1] + 1) : 1; + down[i] = Math.max(down[i], t); + + if (arr[i + 1] < arr[i]) { + down[i] = Math.max(down[i], down[i + 1] + 1); + } else { + down[i] = 1; + } + } + + long answer = 0; + for (int i = 0; i < arr.length; i++) { + answer += Math.max(up[i], down[i]); + } + + return answer; + } +} diff --git a/src/delf/hackerrank/CommonChild.java b/src/delf/hackerrank/CommonChild.java new file mode 100644 index 0000000..d075b3f --- /dev/null +++ b/src/delf/hackerrank/CommonChild.java @@ -0,0 +1,69 @@ +package hackerrank; + +/** + * Common Child + * https://www.hackerrank.com/challenges/common-child/problem + */ +public class CommonChild { + public static void main(String[] args) { +// System.out.println(commonChild("SHINCHAN", "NOHARAAA")); + System.out.println(commonChild("FDAGCXGKCTKWNECHMRXZWMLRYUCOCZHJRRJBOAJOQJZZVUYXIC", "WEWOUCUIDGCGTRMEZEPXZFEJWISRSBBSYXAYDFEJJDLEBVHHKS")); + } + + // 이름있는 알고리즘이었다. 이름하여 'Longest common subsequence problem' + // https://en.wikipedia.org/wiki/Longest_common_subsequence_problem + static int commonChild(String s1, String s2) { + char[] c1 = s1.toCharArray(); + char[] c2 = s2.toCharArray(); + + int[][] dp = new int[c1.length + 1][c2.length + 1]; + + for (int i = 1; i < dp.length; i++) { + for (int j = 1; j < dp[0].length; j++) { + if (c1[i - 1] == c2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + return dp[c1.length][c2.length]; + } + + /* + * 두 문자열을 차례로 탐색하다가 같은 문자열을 만나면, 그 기준으로 다시 탐색하는 풀이 + * 시간초과 + 순서문제 + * */ + static int commonChild2(String s1, String s2) { + int answer = 0; + + char[] s1Arr = s1.toCharArray(); + char[] s2Arr = s2.toCharArray(); + + for (int i = 0; i < s1Arr.length; i++) { + for (int j = 0; j < s2Arr.length; j++) { + int cnt = 0; + if (s1Arr[i] != s2Arr[j]) { + continue; + } + cnt++; + int sj = j + 1; + for (int k = i + 1; k < s1Arr.length; k++) { + for (int l = sj + 1; l < s2Arr.length; l++) { + if (s1Arr[k] == s2Arr[l]) { + sj = l; + cnt++; + break; + } + } + } + answer = Math.max(answer, cnt); + } + } + return answer; + } + + private static boolean test(char[] s1, char[] s2, int si, int sj) { + return false; + } +} diff --git a/src/delf/hackerrank/DavisStaircase.java b/src/delf/hackerrank/DavisStaircase.java new file mode 100644 index 0000000..f7b42b4 --- /dev/null +++ b/src/delf/hackerrank/DavisStaircase.java @@ -0,0 +1,26 @@ +package hackerrank; + +/** + * Recursion: Davis' Staircase + * https://www.hackerrank.com/challenges/ctci-recursive-staircase/problem + */ +public class DavisStaircase { + static int stepPerms(int n) { + if (n < 3) { + return n; + } + if (n == 3) { + return 4; + } + + int[] dp = new int[n]; + + dp[0] = 1; + dp[1] = 2; + dp[2] = 4; + for (int i = 3; i < n; i++) { + dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]; + } + return dp[n - 1]; + } +} diff --git a/src/delf/hackerrank/FraudulentActivityNotifications.java b/src/delf/hackerrank/FraudulentActivityNotifications.java new file mode 100644 index 0000000..fe72af6 --- /dev/null +++ b/src/delf/hackerrank/FraudulentActivityNotifications.java @@ -0,0 +1,112 @@ +package hackerrank; + +import java.util.*; + +/** + * Fraudulent Activity Notifications + * https://www.hackerrank.com/challenges/fraudulent-activity-notifications/problem + */ +public class FraudulentActivityNotifications { + public static void main(String[] args) { +// System.out.println(activityNotifications(new int[]{2, 3, 4, 2, 3, 6, 8, 4, 5}, 5)); + System.out.println(activityNotifications(new int[]{10, 20, 30, 40, 50}, 3)); +// System.out.println(activityNotifications(new int[]{1, 2, 3, 4, 4}, 4)); + // 1 2 3 4 4 + + } + + static int activityNotifications(int[] expenditure, int d) { + int fraudulentCnt = 0; + + int[] nums = new int[201]; + for (int i = 0; i < d; i++) { + nums[expenditure[i]]++; + } + System.out.println(Arrays.toString(nums)); + + for (int i = d; i < expenditure.length; i++) { + int median = getMedian(nums, d); + System.out.println(expenditure[i] + " " + median * 2); + if (expenditure[i] < median * 2) { + fraudulentCnt++; + } + nums[expenditure[d]]++; + nums[expenditure[i - d]]--; + } + return fraudulentCnt; + } + + private static int getMedian(int[] arr, int d) { + final boolean isEven = d % 2 == 0; + int cnt = 0; + int tmp = 0; + for (int i = 0; i < arr.length; i++) { + if (arr[i] == 0) { + continue; + } + cnt += arr[i]; + tmp = i; + if (cnt >= d / 2) { + if (isEven) { + if (cnt == d / 2) { + System.out.println("#1"); + return (i + tmp) / 2; + } + System.out.println("#2"); + return i - 1; + } else { // odd + if (cnt == d / 2) { + System.out.println("#3"); + return i; + } + System.out.println("#4"); + return i + 1; + } + } + /*if (cnt > d / 2) { + System.out.println(String.format("cnt=%d, d/2=%d", cnt, d / 2)); + if (isEven) { + System.out.println("even!"); + if (cnt == d / 2) { + for (int j = i + 1; j < arr.length; j++) { + if (arr[j] != 0) { + System.out.println(String.format("i=%d, j=%d", i, j)); + return (i + j) / 2; + } + } + } else { + return i; + } + } else { // odd + return i - 1; + } + }*/ + } + throw new IllegalArgumentException(); + } + + + static int activityNotifications2(int[] expenditure, int d) { + int fraudulentCnt = 0; + for (int i = 0; i < expenditure.length - d; i++) { + int[] copied = Arrays.copyOfRange(expenditure, i, i + d); + System.out.println(Arrays.toString(copied)); + Arrays.sort(copied); + int median = getMedian2(copied, d); + System.out.println(median); + if (expenditure[i + d] < median * 2) { + fraudulentCnt++; + } + } + return fraudulentCnt; + } + + private static int getMedian2(int[] copied, int d) { + final boolean isOdd = d % 2 != 0; + if (isOdd) { + return copied[d / 2]; + } else { + return (copied[(d / 2) - 1] + copied[d / 2]) / 2; + } + } +} diff --git a/src/delf/hackerrank/FrequencyQueries.java b/src/delf/hackerrank/FrequencyQueries.java new file mode 100644 index 0000000..572d5a4 --- /dev/null +++ b/src/delf/hackerrank/FrequencyQueries.java @@ -0,0 +1,82 @@ +package hackerrank; + +import java.util.*; + +public class FrequencyQueries { + public static void main(String[] args) { + List answer = freqQuery2(Arrays.asList( + new ArrayList<>(Arrays.asList(1, 38)), + new ArrayList<>(Arrays.asList(1, 38)), + new ArrayList<>(Arrays.asList(1, 400)), + new ArrayList<>(Arrays.asList(1, 400)), + new ArrayList<>(Arrays.asList(1, 400)), + new ArrayList<>(Arrays.asList(1, 400)), + new ArrayList<>(Arrays.asList(2, 400)), + new ArrayList<>(Arrays.asList(2, 38)), + new ArrayList<>(Arrays.asList(2, 38)), + new ArrayList<>(Arrays.asList(2, 38)), + new ArrayList<>(Arrays.asList(3, 0)) + )); + System.out.println(answer); + } + + static List freqQuery(List> queries) { + List answer = new ArrayList<>(); + + Map idToFrq = new HashMap<>(); + Map freqToCnt = new HashMap<>(); + for (List q : queries) { + int cmd = q.get(0); + int arg = q.get(1); + + switch (cmd) { + case 1: + int frq = idToFrq.merge(arg, 1, Integer::sum); + if (frq > 1) { + freqToCnt.merge(frq - 1, -1, Integer::sum); + } + freqToCnt.merge(frq, 1, Integer::sum); + break; + case 2: + if (!idToFrq.containsKey(arg) || idToFrq.get(arg).equals(0)) { + continue; + } + frq = idToFrq.merge(arg, -1, Integer::sum); + freqToCnt.merge(frq + 1, -1, Integer::sum); + freqToCnt.merge(frq, 1, Integer::sum); + break; + case 3: + answer.add(freqToCnt.containsKey(arg) && !freqToCnt.get(arg).equals(0) ? 1 : 0); + break; + } + } + return answer; + } + + static List freqQuery2(List> queries) { + List answer = new ArrayList<>(); + + Map idToFrq = new HashMap<>(); + for (List q : queries) { + int cmd = q.get(0); + int arg = q.get(1); + + switch (cmd) { + case 1: + idToFrq.merge(arg, 1, Integer::sum); + break; + case 2: + if(!idToFrq.containsKey(arg) || idToFrq.get(arg).equals(0)) { + continue; + } + idToFrq.merge(arg, -1, Integer::sum); + break; + case 3: + answer.add(idToFrq.containsValue(arg) ? 1 : 0); + break; + } + } + System.out.println(idToFrq); + return answer; + } +} diff --git a/src/delf/hackerrank/HuffmanDecoding.java b/src/delf/hackerrank/HuffmanDecoding.java new file mode 100644 index 0000000..c418d99 --- /dev/null +++ b/src/delf/hackerrank/HuffmanDecoding.java @@ -0,0 +1,30 @@ +package hackerrank; + +import java.util.Objects; + +/** + * Huffman Decoding + * https://www.hackerrank.com/challenges/tree-huffman-decoding/problem + */ +public class HuffmanDecoding { + static void decode(String s, Node root) { + String answer = ""; + Node base = Objects.requireNonNull(root); + while (!s.isEmpty()) { + base = s.charAt(0) == '1' ? Objects.requireNonNull(base.right) : Objects.requireNonNull(base.left); + s = s.substring(1); + + if (Objects.isNull(base.left) && Objects.isNull(base.right)) { + answer += base.data; + base = root; + } + } + System.out.println(answer); + } + + class Node { + public int frequency; // the frequency of this tree + public char data; + public Node left, right; + } +} diff --git a/src/delf/hackerrank/IsThisABinarySearchTree.java b/src/delf/hackerrank/IsThisABinarySearchTree.java new file mode 100644 index 0000000..07f8d73 --- /dev/null +++ b/src/delf/hackerrank/IsThisABinarySearchTree.java @@ -0,0 +1,27 @@ +package hackerrank; + +import com.sun.corba.se.pept.encoding.InputObject; + +public class IsThisABinarySearchTree { + boolean checkBST(Node root) { + return isBinarySearchTree(root); + } + + private boolean isBinarySearchTree(Node node) { + if (node.left == null) { + return node.right == null; + } else { + if (node.right == null) { + return false; + } else { + return (node.left.data < node.data && node.data < node.right.data) && (isBinarySearchTree(node.left) && isBinarySearchTree(node.right)); + } + } + } + + class Node { + int data; + Node left; + Node right; + } +} diff --git a/src/delf/hackerrank/LargestRectangle.java b/src/delf/hackerrank/LargestRectangle.java new file mode 100644 index 0000000..c9fc4ea --- /dev/null +++ b/src/delf/hackerrank/LargestRectangle.java @@ -0,0 +1,32 @@ +package hackerrank; + +import java.util.Stack; + +/** + * Largest Rectangle + * https://www.hackerrank.com/challenges/largest-rectangle/problem + */ +public class LargestRectangle { + static long largestRectangle(int[] h) { + Stack stack = new Stack<>(); + int maxArea = 0; + int top; + + int i = 0; + while (i < h.length) { + if (stack.empty() || h[stack.peek()] <= h[i]) { + stack.push(i++); + } else { + top = h[stack.pop()] * (stack.empty() ? i : i - stack.peek() - 1); + maxArea = Math.max(maxArea, top); + } + } + + while (!stack.empty()) { + top = h[stack.pop()] * (stack.empty() ? i : i - stack.peek() - 1); + maxArea = Math.max(maxArea, top); + } + + return maxArea; + } +} diff --git a/src/delf/hackerrank/MaxArraySum.java b/src/delf/hackerrank/MaxArraySum.java new file mode 100644 index 0000000..c6e1c78 --- /dev/null +++ b/src/delf/hackerrank/MaxArraySum.java @@ -0,0 +1,31 @@ +package hackerrank; + +/** + * Max Array Sum + * https://www.hackerrank.com/challenges/max-array-sum/problem + */ +public class MaxArraySum { + public static void main(String[] args) { + System.out.println(maxSubsetSum(new int[]{3, 5, -7, 8, 10})); + } + + static int maxSubsetSum(int[] arr) { + int[] dp = new int[arr.length + 1]; + dp[0] = 0; + dp[1] = arr[0]; + dp[2] = arr[1]; + + int max = 0; + for (int i = 3; i <= arr.length; i++) { + int tmpMax = Math.max(dp[i - 2], dp[i - 3]); + if (arr[i - 1] >= 0) { + dp[i] = Math.max(arr[i - 1], tmpMax + arr[i - 1]); + } else { + dp[i] = tmpMax; + } + + max = Math.max(max, dp[i]); + } + return max; + } +} diff --git a/src/delf/hackerrank/MinMaxRiddle.java b/src/delf/hackerrank/MinMaxRiddle.java new file mode 100644 index 0000000..abddbd2 --- /dev/null +++ b/src/delf/hackerrank/MinMaxRiddle.java @@ -0,0 +1,62 @@ +package hackerrank; + +import java.util.*; + +/** + * Min Max Riddle + * https://www.hackerrank.com/challenges/min-max-riddle/problem + */ +public class MinMaxRiddle { + static long[] riddle(int[] arr) { + int[] lefts = leftWinSize(arr); + int[] rights = rightWinSize(arr); + + SortedMap map = new TreeMap<>(Collections.reverseOrder()); + + for (int i = 0; i < arr.length; i++) { + map.put(arr[i], Math.max(map.getOrDefault(arr[i], -1), lefts[i] + rights[i] + 1)); + } + + Iterator iter = map.keySet().iterator(); + int number = iter.next(); + long[] result = new long[arr.length]; + + for (int i = 0; i < result.length; i++) { + while (map.get(number) <= i) { + number = iter.next(); + } + result[i] = number; + } + return result; + } + + static int[] leftWinSize(int[] arr) { + int[] lefts = new int[arr.length]; + Stack indices = new Stack<>(); + + for (int i = 0; i < arr.length; i++) { + while (!indices.isEmpty() && arr[i] <= arr[indices.peek()]) { + indices.pop(); + } + lefts[i] = i - (indices.isEmpty() ? 0 : indices.peek() + 1); + indices.push(i); + } + + return lefts; + } + + static int[] rightWinSize(int[] arr) { + int[] rights = new int[arr.length]; + Stack indices = new Stack<>(); + + for (int i = arr.length - 1; i >= 0; i--) { + while (!indices.isEmpty() && arr[i] <= arr[indices.peek()]) { + indices.pop(); + } + + rights[i] = (indices.isEmpty() ? arr.length : indices.peek()) - (i + 1); + indices.push(i); + } + return rights; + } +} diff --git a/src/delf/hackerrank/MinimumSwap2.java b/src/delf/hackerrank/MinimumSwap2.java new file mode 100644 index 0000000..111edee --- /dev/null +++ b/src/delf/hackerrank/MinimumSwap2.java @@ -0,0 +1,21 @@ +package hackerrank; + +/* Minimum Swaps 2 + * https://www.hackerrank.com/challenges/minimum-swaps-2/problem + * */ +public class MinimumSwap2 { + static int minimumSwaps(int[] arr) { + int cnt = 0; + for (int i = 0; i < arr.length; i++) { + int idx = arr[i]; + if (idx == (i + 1)) { + continue; + } + arr[i] = arr[idx - 1]; + arr[idx - 1] = idx; + cnt++; + i--; + } + return cnt; + } +} \ No newline at end of file diff --git a/src/delf/hackerrank/MinimumTimeRequired.java b/src/delf/hackerrank/MinimumTimeRequired.java new file mode 100644 index 0000000..813d504 --- /dev/null +++ b/src/delf/hackerrank/MinimumTimeRequired.java @@ -0,0 +1,34 @@ +package hackerrank; + +import java.util.Arrays; + +/** + * Minimum Time Required + * https://www.hackerrank.com/challenges/minimum-time-required/problem + */ +public class MinimumTimeRequired { + + static long minTime(long[] machines, long goal) { + Arrays.sort(machines); + return binarySearchRecursive(machines, goal, 1, machines[machines.length - 1] * goal); + } + + static long binarySearchRecursive(long[] machines, long goal, long min, long max) { + if (min == max) { + return min; + } + + long mid = (min + max) / 2; + long produce = 0; + + for (long machine : machines) { + produce += Math.floor((double) (mid / machine)); + } + + if (produce < goal) { + return binarySearchRecursive(machines, goal, mid + 1, max); + } else { + return binarySearchRecursive(machines, goal, min, mid); + } + } +} diff --git a/src/delf/hackerrank/NewYearChaos.java b/src/delf/hackerrank/NewYearChaos.java new file mode 100644 index 0000000..122b379 --- /dev/null +++ b/src/delf/hackerrank/NewYearChaos.java @@ -0,0 +1,67 @@ +package hackerrank; + +/* New Year Chaos + * https://www.hackerrank.com/challenges/new-year-chaos + * */ +public class NewYearChaos { + + static void minimumBribes2(int[] q) { + for (int i = 0; i < q.length; i++) { + if (q[i] - (i + 1) > 2) { + System.out.println("Too chaotic"); + return; + } + } + + int cnt = 0; + for (int i = 0; i < q.length; i++) { + if (i + 1 == q[i]) { + continue; + } + int idx = i + 1; + for (int j = idx; j < q.length; j++) { + if (q[j] == idx) { + int tmp = q[j - 1]; + q[j - 1] = q[j]; + q[j] = tmp; + cnt++; + i--; + break; + } + } + } + System.out.println(cnt); + } + + static void minimumBribes(int[] q) { + int[] b = new int[q.length]; + int cnt = 0; + for (int i = 0; i < q.length; i++) { + for (int j = i + 1; j < q.length; j++) { + if (q[i] > q[j]) { + cnt++; + b[q[i] - 1]++; + if (b[q[i] - 1] > 2) { + System.out.println("Too chaotic"); + return; + } + } + } + } + System.out.println(cnt); + } + + + public static void main(String[] args) { +// minimumBribes(new int[]{1, 2, 3, 4, 5, 6, 7, 8}); // tc +// minimumBribes(new int[]{5, 1, 2, 3, 7, 8, 6, 4}); // tc + minimumBribes2(new int[]{1, 2, 5, 3, 7, 8, 6, 4}); // 7 +// minimumBribes(new int[]{1, 2, 3, 4, 5}); // 3 +// minimumBribes(new int[]{2, 1, 5, 3, 4}); // 3 +// minimumBribes(new int[]{2, 1, 5, 3, 4}); // 3 +// minimumBribes(new int[]{2, 5, 1, 3, 4}); // tc + +// minimumBribes(new int[]{1, 2, 3, 4, 5}); + } +} + diff --git a/src/delf/hackerrank/Pairs.java b/src/delf/hackerrank/Pairs.java new file mode 100644 index 0000000..aaeda47 --- /dev/null +++ b/src/delf/hackerrank/Pairs.java @@ -0,0 +1,16 @@ +package hackerrank; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Pairs + * https://www.hackerrank.com/challenges/pairs/problem + */ +public class Pairs { + static int pairs(int k, Integer[] arr) { + Set set = new HashSet<>(Arrays.asList(arr)); + return (int) Arrays.stream(arr).filter(v -> set.contains(v - k)).count(); + } +} diff --git a/src/delf/hackerrank/PoisonousPlants.java b/src/delf/hackerrank/PoisonousPlants.java new file mode 100644 index 0000000..fb78224 --- /dev/null +++ b/src/delf/hackerrank/PoisonousPlants.java @@ -0,0 +1,40 @@ +package hackerrank; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Poisonous Plants + * https://www.hackerrank.com/challenges/poisonous-plants/problem + */ +public class PoisonousPlants { + + public static void main(String[] args) { + System.out.println(poisonousPlants(new int[]{6, 5, 8, 4, 7, 10, 9})); +// System.out.println(poisonousPlants(new int[]{4, 3, 7, 5, 6, 4, 2})); + } + + static int poisonousPlants(int[] p) { + + LinkedList list = Arrays.stream(p).boxed().collect(Collectors.toCollection(LinkedList::new)); + + int answer = 0; + while (true) { + LinkedList tmpList = new LinkedList<>(); + int tmp = list.getFirst(); + tmpList.add(tmp); + for (int i = 1; i < list.size(); i++) { + int n = list.get(i); + if (tmp > n) { + tmpList.add(n); + } + tmp = n; + } + if (list.size() == tmpList.size()) { + return answer; + } + answer++; + list = tmpList; + } + } +} diff --git a/src/delf/hackerrank/ReverseShuffleMerge.java b/src/delf/hackerrank/ReverseShuffleMerge.java new file mode 100644 index 0000000..be9c143 --- /dev/null +++ b/src/delf/hackerrank/ReverseShuffleMerge.java @@ -0,0 +1,38 @@ +package hackerrank; + +import java.util.Arrays; +import java.util.Stack; + +/** + * Reverse Shuffle Merge + * https://www.hackerrank.com/challenges/reverse-shuffle-merge/problem + */ +public class ReverseShuffleMerge { + public static void main(String[] args) { + System.out.println(reverseShuffleMerge2("zbayc")); + } + + static String reverseShuffleMerge2(final String input) { + char[] reversed = new StringBuilder(input).reverse().toString().toCharArray(); + char[] sorted = input.toCharArray(); + Arrays.sort(sorted); + + StringBuilder result = new StringBuilder(); + + int revIdx = 0, srtIdx = 0; + while (revIdx < reversed.length && srtIdx < sorted.length) { + char r = reversed[revIdx]; + char s = sorted[srtIdx]; + + if (r > s) { + result.append(s); + srtIdx++; + } else { + result.append(r); + revIdx++; + } + } + + return result.toString(); + } +} diff --git a/src/delf/hackerrank/SherlockAndAnagram.java b/src/delf/hackerrank/SherlockAndAnagram.java new file mode 100644 index 0000000..3b0d333 --- /dev/null +++ b/src/delf/hackerrank/SherlockAndAnagram.java @@ -0,0 +1,91 @@ +package hackerrank; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * 셜록과 아나그램 + * https://www.hackerrank.com/challenges/sherlock-and-anagrams/problem + */ +public class SherlockAndAnagram { + public static void main(String[] args) { + System.out.println(sherlockAndAnagrams("kkkk")); + } + + static int sherlockAndAnagrams(String s) { + Map counter = new HashMap<>(); + int len = 1; + do { + for (int i = 0; i <= s.length() - len; i++) { + char[] c = s.substring(i, i + len).toCharArray(); + Arrays.sort(c); + counter.merge(new String(c), 1, Integer::sum); + } + } while (len++ < s.length()); + + int cnt = 0; + for (String str : counter.keySet()) { + int n = counter.get(str); + if (n > 1) { + cnt += (n * (n - 1) / 2); + } + } + return cnt; + } + + static int sherlockAndAnagrams2(String s) { + Map counter = new HashMap<>(); + int len = 1; + do { + for (int i = 0; i <= s.length() - len; i++) { + counter.merge(new Anagram(s.substring(i, i + len)), 1, Integer::sum); + } + } while (len++ < s.length()); + + int cnt = 0; + for (Anagram anagram : counter.keySet()) { + int n = counter.get(anagram); + if (n > 1) { + cnt += (n * (n - 1) / 2); + } + } + return cnt; + + } + + static class Anagram { + String string; + + Anagram(String string) { + this.string = string; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + + Anagram a = (Anagram) obj; + + if (this.string.length() != a.string.length()) { + return false; + } + char[] c1 = this.string.toCharArray(); + char[] c2 = a.string.toCharArray(); + Arrays.sort(c1); + Arrays.sort(c2); + return Arrays.equals(c1, c2); + } + + @Override + public int hashCode() { + return 1; + } + + @Override + public String toString() { + return string; + } + } +} \ No newline at end of file diff --git a/src/delf/hackerrank/SherlockAndTheValidString.java b/src/delf/hackerrank/SherlockAndTheValidString.java new file mode 100644 index 0000000..235a692 --- /dev/null +++ b/src/delf/hackerrank/SherlockAndTheValidString.java @@ -0,0 +1,72 @@ +package hackerrank; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Sherlock and the Valid String + * https://www.hackerrank.com/challenges/sherlock-and-valid-string/problem + */ +public class SherlockAndTheValidString { + + public static void main(String[] args) throws IOException { +// System.out.println(isValid("aaaaabc")); +// System.out.println(isValid("aabbccddeefghi")); +// System.out.println(isValid("abcdefghhgfedecba")); + } + + static String isValid(String s) { + return isValidB(s) ? "YES" : "NO"; + } + + private static boolean isValidB(String s) { + Map letterCounter = new HashMap<>(); + for (char ch : s.toCharArray()) { + letterCounter.merge(ch, 1, Integer::sum); + } + if (letterCounter.size() < 2) { + // '문자'가 모두 같은 케이스 (remove 없이도 valid 함) + return true; + } + Map frequencyCounter = new HashMap<>(); + for (int freq : letterCounter.values()) { + frequencyCounter.merge(freq, 1, Integer::sum); + } + + if (frequencyCounter.size() == 1) { + // '빈도수'가 모두 같은 케이스 (remove 없이도 valid 함) + return true; + } + + if (frequencyCounter.size() > 2) { + // '빈도수' 3 이상인 케이스. 즉, remove 한번으로 valid하게 만들기가 불가능 + return false; + } + + int preKey = 0; + int preValue = 0; + for (int key : frequencyCounter.keySet()) { + if (preKey == 0 && preValue == 0) { + preKey = key; + preValue = frequencyCounter.get(key); + continue; + } + if (preKey == 1) { // 가장 적은 빈도수가 한번이고, + // 그런 경우가 하나인 경우 ('문자' 자체가 하나이고, 그걸 remove) + return preValue == 1; + } + // '빈도수'를 하나를 remove 함으로써 다른 빈도수와 같게하는 케이스 + return key - preKey == 1; // + } + throw new IllegalArgumentException(); + } +} + +/* + * # case 1: {}, {a=3} + * # case 2: {a=2, b=2, c=2} + * # case 3: {a=1, b=2, c=3} + * # case 4: {a=1, b=3, c=3}(true), {a=1, b=1, c=3}(false) + * # case 5: {a=5, b=5, c=6}(true) + * */ diff --git a/src/delf/hackerrank/SortComparator.java b/src/delf/hackerrank/SortComparator.java new file mode 100644 index 0000000..ae7b8af --- /dev/null +++ b/src/delf/hackerrank/SortComparator.java @@ -0,0 +1,28 @@ +package hackerrank; + +import java.util.Comparator; + +/** + * Sorting: Comparator + * https://www.hackerrank.com/challenges/ctci-comparator-sorting/problem + */ +public class SortComparator { + static class Checker implements Comparator { + public int compare(Player a, Player b) { + if (a.score == b.score) { + return a.name.compareTo(b.name); + } + return b.score - a.score; + } + } + + static class Player { + String name; + int score; + + Player(String name, int score) { + this.name = name; + this.score = score; + } + } +} diff --git a/src/delf/hackerrank/SpecialStringAgain.java b/src/delf/hackerrank/SpecialStringAgain.java new file mode 100644 index 0000000..5d36e4a --- /dev/null +++ b/src/delf/hackerrank/SpecialStringAgain.java @@ -0,0 +1,101 @@ +package hackerrank; + +import java.util.*; + +/** + * Special String Again + * https://www.hackerrank.com/challenges/special-palindrome-again/problem + */ +/* + * 주어진 문자열을 '문자 덩어리의 배열'로 표현 + * (여기서 문자 덩어리란, 연속된 같은 문자의 모음을 뜻함) + * 1. 각 문자 덩어리 하나로 만들 수 있는 special string의 수를 계산 + * - 연속된 부분집합의 개수. S(n)라는 집합이 있으면, 1+2+...+n. 즉 n*(n+1)/2 + * 2. 여러개의 문자 덩어리로 만들 수 있는 special string의 수를 계산 + * - 문자 덩어리를 세개를 기준으로, 가운데 문자 덩어리의 개수가 1이면서 양쪽의 문자가 같은 경우 + * - 양쪽 문자 덩어리의 개수중 적은 쪽이 special string + * - ex) bbabbb (b=2, a=1, b=3) -> bab, bbabb 두가지 + * */ +public class SpecialStringAgain { + static long substrCount(String s) { + List list = new ArrayList<>(); + char[] arr = s.toCharArray(); + char tmp = arr[0]; + int cnt = 1; + for (int i = 1; i < arr.length; i++) { + if (tmp != arr[i]) { + list.add(new CharacterChunk(tmp, cnt)); + cnt = 0; + tmp = arr[i]; + } + cnt++; + } + list.add(new CharacterChunk(tmp, cnt)); + + int answer = 0; + for (CharacterChunk characterChunk : list) { + int n = characterChunk.q; + answer += (n * (n + 1) / 2); + } + + for (int i = 1; i < list.size() - 1; i++) { + if (list.get(i).q != 1) { + continue; + } + if (list.get(i - 1).v != list.get(i + 1).v) { + continue; + } + answer += (Math.min(list.get(i - 1).q, list.get(i + 1).q)); + } + return answer; + } + + static class CharacterChunk { + char v; // value + int q; // quantity + + CharacterChunk(char value, int quantity) { + this.v = value; + this.q = quantity; + } + } + + + static long substrCount2(int n, String s) { + int len = 1; + long cnt = 0; + char[] arr = s.toCharArray(); + do { + for (int i = 0; i <= s.length() - len; i++) { + cnt += isSpecialString(arr, i, i + len) ? 1 : 0; + } + } while (len++ < s.length()); + + return cnt; + } + + private static boolean isSpecialString(char[] s, int start, int end) { + int len = end - start; + if (len < 2) { + return true; + } + + char first = s[start]; + if (len % 2 == 0) { + for (int i = start + 1; i < end; i++) { + if (first != s[i]) { + return false; + } + } + } else { + for (int i = start + 1; i < end; i++) { + if (first != s[i]) { + if (i - start != (len / 2)) { + return false; + } + } + } + } + return true; + } +} diff --git a/src/delf/hackerrank/TripleSum.java b/src/delf/hackerrank/TripleSum.java new file mode 100644 index 0000000..d7bd305 --- /dev/null +++ b/src/delf/hackerrank/TripleSum.java @@ -0,0 +1,31 @@ +package hackerrank; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Triple sum + * https://www.hackerrank.com/challenges/triple-sum/problem + */ +public class TripleSum { + static long triplets(int[] a, int[] b, int[] c) { + List listA = Arrays.stream(a).sorted().distinct().boxed().collect(Collectors.toList()); + List listB = Arrays.stream(b).sorted().distinct().boxed().collect(Collectors.toList()); + List listC = Arrays.stream(c).sorted().distinct().boxed().collect(Collectors.toList()); + + long answer = 0; + + int countA = 0, countB = 0, countC = 0; + while (countB < b.length) { + while (countA < a.length && listA.get(countA) <= listB.get(countB)) { + countA++; + } + while (countC < c.length && listC.get(countC) <= listB.get(countB)) { + countC++; + } + answer += (long) countA * (long) countC; + countB++; + } + return answer; + } +} diff --git a/src/delf/interviewguidemission/StackMission1.java b/src/delf/interviewguidemission/StackMission1.java new file mode 100644 index 0000000..f7247b2 --- /dev/null +++ b/src/delf/interviewguidemission/StackMission1.java @@ -0,0 +1,29 @@ +package interviewguidemission; + +import java.util.Arrays; +import java.util.List; + +public class StackMission1 { + public static void main(String[] args) { + System.out.println(new StackMission1().solution("[{1+2*(2+2)}-(1-3)]", 1)); + } + + public int solution(String s, int index) { + List open = Arrays.asList('(', '{', '['); + List close = Arrays.asList(')', '}', ']'); + char openTarget = s.charAt(index); + char closeTarget = close.get(open.indexOf(openTarget)); + boolean listen = false; + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (ch == openTarget) { + listen = true; + continue; + } + if (listen && ch == closeTarget) { + return i; + } + } + throw new IllegalStateException(); + } +} \ No newline at end of file diff --git a/src/delf/interviewguidemission/StackMission2.java b/src/delf/interviewguidemission/StackMission2.java new file mode 100644 index 0000000..ffdefa2 --- /dev/null +++ b/src/delf/interviewguidemission/StackMission2.java @@ -0,0 +1,43 @@ +package interviewguidemission; + +import java.util.*; + +public class StackMission2 { + public static void main(String[] args) { + System.out.println(new StackMission2().solution("{{{}}")); + System.out.println(new StackMission2().solution("{{{{}}")); + System.out.println(new StackMission2().solution("}}}}{}}}")); + System.out.println(new StackMission2().solution("{{{{")); + } + public int solution(String s) { + Stack stack = new Stack<>(); + int cnt = 0; + for (char ch : s.toCharArray()) { + if (stack.isEmpty()) { + if (ch == '}') { + cnt++; + stack.push('{'); + } else { + stack.push(ch); + } + continue; + } + + if (ch == '{') { + stack.push(ch); + } else if (ch == '}' && stack.peek() == '{') { + stack.pop(); + } + } + + if (stack.isEmpty()) { + return cnt; + } + + if (stack.size() % 2 != 0) { + return -1; + } + + return cnt + stack.size() / 2; + } +} diff --git a/src/delf/oncoder/Challenge10.java b/src/delf/oncoder/Challenge10.java new file mode 100644 index 0000000..dfa4f13 --- /dev/null +++ b/src/delf/oncoder/Challenge10.java @@ -0,0 +1,21 @@ +package oncoder; + +/** + * 평형점 구하기 + * https://www.oncoder.com/ground/BkIQ8NT0Q + */ +public class Challenge10 { + public static void main(String[] args) { + System.out.println(new Challenge10().solution(-1, 1, 2, 1000)); + } + + public double solution(int x1, int m1, int x2, int m2) { + if (m1 == m2) { + return (double) (x1 + x2) / 2.0; + } + int biggerX = Math.max(x1, x2); + int smallerX = Math.min(x1, x2); + return smallerX + ((m1 - Math.sqrt(m1) * Math.sqrt(m2)) * (biggerX - smallerX)) / (m1 - m2); + } + +} diff --git a/src/delf/oncoder/Challenge11.java b/src/delf/oncoder/Challenge11.java new file mode 100644 index 0000000..84c687d --- /dev/null +++ b/src/delf/oncoder/Challenge11.java @@ -0,0 +1,23 @@ +package oncoder; + +/** + * 잔액 계산 + * https://www.oncoder.com/ground/rJjZchpRX + */ +public class Challenge11 { + public int solution(int balance, String[] transactions) { + for (String tr : transactions) { + String[] args = tr.split(" "); + String cmd = args[0]; + int amount = Integer.parseInt(args[1]); + + if (cmd.equals("C")) { + balance += amount; + continue; + } + + balance -= amount; + } + return balance; + } +} diff --git a/src/delf/oncoder/Challenge12.java b/src/delf/oncoder/Challenge12.java new file mode 100644 index 0000000..4762a20 --- /dev/null +++ b/src/delf/oncoder/Challenge12.java @@ -0,0 +1,33 @@ +package oncoder; + +/** + * 대선 전략 수립 + * https://www.oncoder.com/ground/SkmYcmk1E + */ +public class Challenge12 { + public int solution(String[] stats){ + double minRatio = 1; + int minStat = 0; + for (int i = 0; i < stats.length; i++) { + int one = 0; + int two = 0; + for (char ch : stats[i].toCharArray()) { + if (ch == '1') { + one++; + continue; + } + two++; + } + double ratio = (double) one / (double) (one + two); + if (minRatio > ratio) { + minRatio = ratio; + minStat = i; + } + } + return minStat; + } + + public static void main(String[] args) { + System.out.println(new Challenge12().solution(new String[]{"111", "112", "121", "122", "211", "212", "221", "222"})); + } +} diff --git a/src/delf/oncoder/Challenge13.java b/src/delf/oncoder/Challenge13.java new file mode 100644 index 0000000..2f88e1a --- /dev/null +++ b/src/delf/oncoder/Challenge13.java @@ -0,0 +1,23 @@ +package oncoder; + +import java.util.*; + +/** + * @author delf + */ +public class Challenge13 { + public int[] solution(int[] sequence) { + List list = new ArrayList<>(); + for (int i : sequence) { + if (list.contains(i)) { + list.remove((Integer) i); + } + list.add(i); + } + return list.stream().mapToInt(Integer::intValue).toArray(); + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(new Challenge13().solution(new int[]{1, 2, 5, 4, 4, 4, 2, 3}))); + } +} diff --git a/src/delf/oncoder/Challenge14.java b/src/delf/oncoder/Challenge14.java new file mode 100644 index 0000000..63a6e4c --- /dev/null +++ b/src/delf/oncoder/Challenge14.java @@ -0,0 +1,23 @@ +package oncoder; + +/** + * @author delf + */ +public class Challenge14 { + public static void main(String[] args) { + System.out.println(new Challenge14().solution(7, 3, 1)); + System.out.println(new Challenge14().solution(5, 3, 2)); + System.out.println(new Challenge14().solution(5, 5, 3)); + } + + public String solution(int n1, int n2, int K) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < n1; i++) { + sb.append("M"); + } + for (int i = 0; i < n2; i++) { + sb.insert(((K - 1) + (K * i)) % sb.length(), "F"); + } + return sb.toString(); + } +} diff --git a/src/delf/oncoder/Challenge16.java b/src/delf/oncoder/Challenge16.java new file mode 100644 index 0000000..570ae78 --- /dev/null +++ b/src/delf/oncoder/Challenge16.java @@ -0,0 +1,44 @@ +package oncoder; + +import java.util.*; + + +/** + * @author delf + */ +public class Challenge16 { + public static void main(String[] args) { + System.out.println(new Challenge16().solution(new int[]{10, 20, 30, 40, 50})); + System.out.println(new Challenge16().solution(new int[]{123, 123, 456, 456, 456, 123})); + System.out.println(new Challenge16().solution(new int[]{1, 2, 2, 3, 3, 3, 4, 4, 4, 4})); + + + } + + public int solution(int[] events) { + Map solveCounter = new LinkedHashMap<>(); + Map orderCounter = new HashMap<>(); + for (int i = 0; i < events.length; i++) { + solveCounter.merge(events[i], 1, Integer::sum); + orderCounter.putIfAbsent(events[i], i); + } + System.out.println(solveCounter); + System.out.println(orderCounter); + + int maxKey = 0; + int maxValue = 0; + for (int key : solveCounter.keySet()) { + maxValue = Math.max(maxValue, solveCounter.get(key)); + int value = solveCounter.get(key); + if (maxValue > value) { + maxValue = value; + maxKey = key; + } else if (maxValue == value) { + if (orderCounter.get(key) > orderCounter.get(maxKey)) { + maxKey = key; + } + } + } + return maxKey; + } +} diff --git a/src/delf/oncoder/Challenge5.java b/src/delf/oncoder/Challenge5.java new file mode 100644 index 0000000..4ea5c1e --- /dev/null +++ b/src/delf/oncoder/Challenge5.java @@ -0,0 +1,21 @@ +package oncoder; + +/** + * 13 구하기 + * https://www.oncoder.com/ground/B12g8N6RX + */ +public class Challenge5 { + public int solution(int a) { + int cnt = 0; + for (int i = 1; i <= a; i++) { + int tmp = i; + do { + if ((tmp - 13) % 100 == 0) { + cnt++; + break; + } + } while ((tmp /= 10) > 0); + } + return cnt; + } +} diff --git a/src/delf/oncoder/Challenge6.java b/src/delf/oncoder/Challenge6.java new file mode 100644 index 0000000..3147f1a --- /dev/null +++ b/src/delf/oncoder/Challenge6.java @@ -0,0 +1,26 @@ +package oncoder; + +/** + * 셀프넘버 판별 + * https://www.oncoder.com/ground/B12g8N6RX + */ +public class Challenge6 { + public int solution(int a) { + int cnt = 0; + for (int i = 1; i <= a; i++) { + if (F(i) == a) { + cnt++; + } + } + return cnt; + } + + private static int F(final int n) { + int sum = 0; + int cursor = n; + do { + sum += cursor % 10; + } while ((cursor /= 10) > 0); + return n + sum; + } +} diff --git a/src/delf/oncoder/Challenge7.java b/src/delf/oncoder/Challenge7.java new file mode 100644 index 0000000..d4964f4 --- /dev/null +++ b/src/delf/oncoder/Challenge7.java @@ -0,0 +1,17 @@ +package oncoder; + +import java.util.Arrays; + +/** + * 정렬하기 + * https://www.oncoder.com/ground/rJwbIEaRm + */ +public class Challenge7 { + public int[] solution(int[] arr) { + return Arrays.stream(arr) + .mapToObj(String::valueOf) + .sorted(String::compareTo) + .mapToInt(Integer::parseInt) + .toArray(); + } +} diff --git a/src/delf/programmers/Solution12905.java b/src/delf/programmers/Solution12905.java new file mode 100644 index 0000000..88fde14 --- /dev/null +++ b/src/delf/programmers/Solution12905.java @@ -0,0 +1,33 @@ +package programmers; + +/** + * 가장 큰 정사각형 + * https://programmers.co.kr/learn/courses/30/lessons/12905 + */ +public class Solution12905 { + public int solution(int[][] board) { + int up, left, upLeft; + for (int i = 1; i < board.length; i++) { + for (int j = 1; j < board[i].length; j++) { + if (board[i][j] == 1) { + up = board[i - 1][j]; + left = board[i][j - 1]; + upLeft = board[i - 1][j - 1]; + + int min = Math.min(Math.min(up, left), upLeft); + board[i][j] = min + 1; + } + } + } + + int ans = 0; + for (int[] n : board) { + for (int j = 0; j < board[0].length; j++) { + if (n[j] > 0) { + ans = Math.max(ans, n[j]); + } + } + } + return ans * ans; + } +} diff --git a/src/delf/programmers/Solution12907.java b/src/delf/programmers/Solution12907.java new file mode 100644 index 0000000..84af624 --- /dev/null +++ b/src/delf/programmers/Solution12907.java @@ -0,0 +1,37 @@ +package programmers; + +import java.util.Arrays; + +/** + * 거스름 + * https://programmers.co.kr/learn/courses/30/lessons/12907 + */ +public class Solution12907 { + static final int MOD = 1000000007; + + public static void main(String[] args) { + System.out.println(new Solution12907().solution(10, new int[]{2, 3, 5})); + } + + public int solution(int n, int[] money) { + int[][] dp = new int[money.length + 1][n + 1]; + + Arrays.sort(money); + + dp[0][0] = 1; + + for (int r = 1; r < dp.length; ++r) { + for (int c = 0; c < dp[0].length; ++c) { + if (c < money[r - 1]) { + dp[r][c] = dp[r - 1][c] % MOD; + } else if (c == money[r - 1]) { + dp[r][c] = dp[r - 1][c] + 1 % MOD; + } else { + dp[r][c] = dp[r - 1][c] + dp[r][c - money[r - 1]] % MOD; + } + } + } + + return dp[money.length][n]; + } +} diff --git a/src/delf/programmers/Solution12913.java b/src/delf/programmers/Solution12913.java new file mode 100644 index 0000000..2b17a8f --- /dev/null +++ b/src/delf/programmers/Solution12913.java @@ -0,0 +1,27 @@ +package programmers; + +import java.util.Arrays; + +public class Solution12913 { + public int solution(int[][] land) { + for (int j = 0; j < land.length; j++) { + for (int i = 0; i < land[j].length; i++) { + if (j == 0) continue; + land[j][i] += getMaxExcept(land[j - 1], i); + } + } + + return Arrays.stream(land[land.length - 1]).max().getAsInt(); + } + + private int getMaxExcept(int[] arr, int index) { + int max = 0; + for (int i = 0; i < arr.length; i++) { + if (i == index) { + continue; + } + max = Math.max(max, arr[i]); + } + return max; + } +} diff --git a/src/delf/programmers/Solution12927.java b/src/delf/programmers/Solution12927.java new file mode 100644 index 0000000..3670e20 --- /dev/null +++ b/src/delf/programmers/Solution12927.java @@ -0,0 +1,48 @@ +package programmers; + +import java.util.stream.IntStream; + +/** + * 야근 지수 + * https://programmers.co.kr/learn/courses/30/lessons/12927 + */ +public class Solution12927 { + public static long solution(int n, int[] works) { + int[] result = new int[works.length]; + int total = IntStream.of(works).sum() - n; + int time = total; + + if (time <= 0) { + return 0; + } + + for (int i = 0; i < works.length; i++) { + result[i] = Math.min(works[i], total / works.length); + time -= result[i]; + } + + for (int i = 0; i < works.length; i++) { + if (time <= 0) { + break; + } + if (works[i] > result[i]) { + result[i]++; + time--; + } + if (i == works.length - 1) { + i = -1; + } + } + + int sum = 0; + for (int work : result) { + sum += (work * work); + } + return sum; + } + + + public static void main(String[] args) { + System.out.println(solution(4, new int[]{4, 3, 3})); + } +} diff --git a/src/delf/programmers/Solution12938.java b/src/delf/programmers/Solution12938.java new file mode 100644 index 0000000..0c76909 --- /dev/null +++ b/src/delf/programmers/Solution12938.java @@ -0,0 +1,26 @@ +package programmers; + +import java.util.Arrays; + +/** + * 최고의 집합 + * https://programmers.co.kr/learn/courses/30/lessons/12938 + */ +public class Solution12938 { + public int[] solution(int n, int s) { + int div = s / n; + if (div == 0) { + return new int[]{-1}; + } + + int[] answer = new int[n]; + Arrays.fill(answer, div); + + int rest = s % n; + for (int i = 0; i < rest; i++) { + answer[n - 1 - i]++; + } + + return answer; + } +} diff --git a/src/delf/programmers/Solution12941.java b/src/delf/programmers/Solution12941.java new file mode 100644 index 0000000..929ad91 --- /dev/null +++ b/src/delf/programmers/Solution12941.java @@ -0,0 +1,24 @@ +package programmers; + +import java.util.Arrays; + +/** + * 최솟값 만들기 + * https://programmers.co.kr/learn/courses/30/lessons/12941 + */ +public class Solution12941 { + public int solution(int[] A, int[] B) { + int answer = 0; + Arrays.sort(A); + Arrays.sort(B); + for (int i = 0; i < A.length; i++) { + answer += (A[i] * B[B.length - (i + 1)]); + } + return answer; + } + + public static void main(String[] args) { + System.out.println(new Solution12941().solution(new int[]{1, 4, 2}, new int[]{5, 4, 4})); + + } +} diff --git a/src/delf/programmers/Solution12952.java b/src/delf/programmers/Solution12952.java new file mode 100644 index 0000000..b53dc03 --- /dev/null +++ b/src/delf/programmers/Solution12952.java @@ -0,0 +1,39 @@ +package programmers; + +public class Solution12952 { + public static int[] arr; + public static int count = 0; + + public static void main(String[] args) { + System.out.println(new Solution12952().solution(8)); + } + + public int solution(int n) { + return dfs(new int[n * n], n, 0); + } + + public static int dfs(int[] arr, int n, int depth) { + if (depth == n) { + return 1; + } + int cnt = 0; + for (int i = 0; i < n; i++) { + arr[depth] = i; + if (isPlacedQueens(arr, depth)) { + cnt += dfs(arr, n, depth + 1); + } + } + return cnt; + } + + public static boolean isPlacedQueens(int[] arr, int col) { + for (int i = 0; i < col; i++) { + if (arr[col] == arr[i]) { + return false; + } else if (Math.abs(col - i) == Math.abs(arr[col] - arr[i])) { + return false; + } + } + return true; + } +} diff --git a/src/delf/programmers/Solution12973.java b/src/delf/programmers/Solution12973.java new file mode 100644 index 0000000..4a1707a --- /dev/null +++ b/src/delf/programmers/Solution12973.java @@ -0,0 +1,33 @@ +package programmers; + +import java.util.Stack; + +/** + * 짝지어 제거하기 + * https://programmers.co.kr/learn/courses/30/lessons/12973 + */ +public class Solution12973 { + public static void main(String[] args) { + System.out.println(new Solution12973().solution("cdcd")); + System.out.println(new Solution12973().solution("baabaa")); + } + + public int solution(String s) { + Stack stack = new Stack<>(); + for (char ch : s.toCharArray()) { + if (stack.isEmpty()) { + stack.push(ch); + continue; + } + + if (stack.peek() == ch) { + stack.pop(); + continue; + } + + stack.push(ch); + } + + return stack.isEmpty() ? 1 : 0; + } +} diff --git a/src/delf/programmers/Solution12980.java b/src/delf/programmers/Solution12980.java new file mode 100644 index 0000000..bdd5f27 --- /dev/null +++ b/src/delf/programmers/Solution12980.java @@ -0,0 +1,25 @@ +package programmers; + +/** + * 점프와 순간 이동 + * https://programmers.co.kr/learn/courses/30/lessons/12980 + */ +public class Solution12980 { + public static void main(String[] args) { + System.out.println(new Solution12980().solution(5)); + System.out.println(new Solution12980().solution(6)); + System.out.println(new Solution12980().solution(5000)); + } + + public int solution(int n) { + int cnt = 0; + while (n > 0) { + if (n % 2 != 0) { + cnt++; + n--; + } + n /= 2; + } + return cnt; + } +} \ No newline at end of file diff --git a/src/delf/programmers/Solution12985.java b/src/delf/programmers/Solution12985.java new file mode 100644 index 0000000..bc827f7 --- /dev/null +++ b/src/delf/programmers/Solution12985.java @@ -0,0 +1,23 @@ +package programmers; + +/** + * 예상 대진표 + * https://programmers.co.kr/learn/courses/30/lessons/12985 + */ +public class Solution12985 { + public static void main(String[] args) { + System.out.println(">>" + new Solution12985().solution(8, 1, 2)); // 1 + System.out.println(">>" + new Solution12985().solution(8, 2, 3)); // 2 + System.out.println(">>" + new Solution12985().solution(8, 4, 7)); // 3 + } + + public int solution(int n, int a, int b) { + int answer = 0; + do { + a = (a + 1) / 2; + b = (b + 1) / 2; + answer++; + } while (Math.abs(a - b) > 0); + return answer; + } +} diff --git a/src/delf/programmers/Solution12987.java b/src/delf/programmers/Solution12987.java new file mode 100644 index 0000000..e29964e --- /dev/null +++ b/src/delf/programmers/Solution12987.java @@ -0,0 +1,28 @@ +package programmers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; +/** + * 숫자 게임 + * https://programmers.co.kr/learn/courses/30/lessons/12987 + **/ +public class Solution12987 { + public int solution(int[] A, int[] B) { + Arrays.sort(A); + Arrays.sort(B); + Queue qA = new LinkedList<>(new ArrayList<>(Arrays.asList(Arrays.stream(A).boxed().toArray(Integer[]::new)))); + Queue qB = new LinkedList<>(new ArrayList<>(Arrays.asList(Arrays.stream(B).boxed().toArray(Integer[]::new)))); + + int answer = 0; + while (!qA.isEmpty() && !qB.isEmpty()) { + if (qA.peek() < qB.peek()) { + qA.poll(); + answer++; + } + qB.poll(); + } + return answer; + } +} diff --git a/src/delf/programmers/Solution17676.java b/src/delf/programmers/Solution17676.java new file mode 100644 index 0000000..7a4e22c --- /dev/null +++ b/src/delf/programmers/Solution17676.java @@ -0,0 +1,64 @@ +package programmers; + +/** + * 추석 트래픽 + * https://programmers.co.kr/learn/courses/30/lessons/17676 + */ +public class Solution17676 { + public int solution(String[] lines) { + int answer = 0; + int[] startTimes = new int[lines.length]; + int[] endTimes = new int[lines.length]; + + getTimes(lines, startTimes, endTimes); + + for (int i = 0; i < lines.length; i++) { + int cnt = 0; + int startOfSection = startTimes[i]; + int endOfSection = startOfSection + 1000; + + answer = getAnswer(lines, answer, startTimes, endTimes, cnt, startOfSection, endOfSection); + + cnt = 0; + startOfSection = endTimes[i]; + endOfSection = startOfSection + 1000; + + answer = getAnswer(lines, answer, startTimes, endTimes, cnt, startOfSection, endOfSection); + } + + return answer; + } + + private int getAnswer(String[] lines, int answer, int[] startTimes, int[] endTimes, int cnt, int startOfSection, int endOfSection) { + for (int j = 0; j < lines.length; ++j) { + if (startTimes[j] >= startOfSection && startTimes[j] < endOfSection) { + cnt++; + } else if (endTimes[j] >= startOfSection && endTimes[j] < endOfSection) { + cnt++; + } else if (startTimes[j] <= startOfSection && endTimes[j] >= endOfSection) { + cnt++; + } + } + + answer = Math.max(cnt, answer); + return answer; + } + + private void getTimes(String[] lines, int[] startTimes, int[] endTimes) { + for (int i = 0; i < lines.length; i++) { + String[] log = lines[i].split(" "); + String[] responseTime = log[1].split(":"); + int processingTime = (int) (Double.parseDouble(log[2].substring(0, log[2].length() - 1)) * 1000); + int startTime = 0; + int endTime = 0; + + endTime += Integer.parseInt(responseTime[0]) * 60 * 60 * 1000; + endTime += Integer.parseInt(responseTime[1]) * 60 * 1000; + endTime += (int) (Double.parseDouble(responseTime[2]) * 1000); + startTime = endTime - processingTime + 1; + + startTimes[i] = startTime; + endTimes[i] = endTime; + } + } +} diff --git a/src/delf/programmers/Solution17677.java b/src/delf/programmers/Solution17677.java new file mode 100644 index 0000000..95e713f --- /dev/null +++ b/src/delf/programmers/Solution17677.java @@ -0,0 +1,82 @@ +package programmers; + +import java.util.*; + +/** + * [1차] 뉴스 클러스터링 + * https://programmers.co.kr/learn/courses/30/lessons/17677 + */ +public class Solution17677 { + public static void main(String[] args) { + System.out.println(new Solution17677().solution("FRANCE", "french")); + System.out.println(new Solution17677().solution("handshake", "shake hands")); + System.out.println(new Solution17677().solution("aa1+aa2", "AAAA12")); + System.out.println(new Solution17677().solution("E=M*C^2", "e=m*c^2")); + } + + private final static int TRANS = 65536; + + public int solution(String str1, String str2) { + Map list1 = generateMap(str1.toLowerCase()); + Map list2 = generateMap(str2.toLowerCase()); + + double intersectionElementsSize = getIntersectionElementsSize(list1, list2); + double unionElementsSize = getUnionElementsSize(list1, list2); + + if (unionElementsSize == 0) { + return TRANS; + } + + return (int) ((intersectionElementsSize / unionElementsSize) * TRANS); + } + + private Map generateMap(String s) { // 다중집합을 map으로 표현 + Map map = new HashMap<>(); + for (int i = 0; i < s.length() - 1; i++) { + if (!Character.isLowerCase(s.charAt(i)) || !Character.isLowerCase(s.charAt(i + 1))) { + continue; + } + map.merge(s.substring(i, i + 2), 1, Integer::sum); + } + + return map; + } + + private int getIntersectionElementsSize(Map map1, Map map2) { + Map result = new HashMap<>(); // 반환용 + for (String key : map1.keySet()) { + if (map2.containsKey(key)) { + int n = Math.min(map1.get(key), map2.get(key)); + result.put(key, n); + } + } + + int cnt = 0; + for (String key : result.keySet()) { // value 카운팅 + cnt += result.get(key); + } + return cnt; + } + + private int getUnionElementsSize(Map map1, Map map2) { + Map result = new HashMap<>(map1); // 반환용(map1 카피) + for (String key : result.keySet()) { // map1과 map2 중 max 값 + if (map2.containsKey(key)) { + int n = Math.max(result.get(key), map2.get(key)); + result.put(key, n); + } + } + + for (String key : map2.keySet()) { // map1에 없는 map2 데이터 추가 + if (!result.containsKey(key)) { + result.put(key, map2.get(key)); + } + } + + int cnt = 0; + for (String key : result.keySet()) { // value 카운팅 + cnt += result.get(key); + } + return cnt; + } +} diff --git a/src/delf/programmers/Solution17678.java b/src/delf/programmers/Solution17678.java new file mode 100644 index 0000000..7898dcb --- /dev/null +++ b/src/delf/programmers/Solution17678.java @@ -0,0 +1,81 @@ +package programmers; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.PriorityQueue; +import java.util.Queue; + +/** + * 셔틀 버스 + * https://programmers.co.kr/learn/courses/30/lessons/17678 + */ +public class Solution17678 { + + public static void main(String[] args) { + System.out.println(new Solution17678().solution(10, 60, 45, new String[]{"23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59"})); +// System.out.println(new Solution17678().solution(1, 1, 5, new String[]{"08:01", "08:04", "08:02", "08:03"})); + } + + public String solution(int n, int t, int m, String[] timetable) { + Queue queue = new PriorityQueue<>(); + for (String value : timetable) { + if (value.equals("24:00")) { + value = "23:59"; + } + queue.add(LocalTime.parse(value, DateTimeFormatter.ofPattern("HH:mm"))); + } + LocalTime bus = LocalTime.parse("09:00", DateTimeFormatter.ofPattern("HH:mm")); + LocalTime corn = LocalTime.parse("09:00", DateTimeFormatter.ofPattern("HH:mm")); + + for (int i = 0; i < n; i++) { + int people = 0; + for (int j = 0; j < m; j++) { + if (!queue.isEmpty()) { + if (bus.isAfter(queue.peek()) || bus.equals(queue.peek())) { + corn = queue.poll(); + people++; + } + } + if (i == n - 1 && people == m) { + corn = corn.minusMinutes(1); + } else if (i == n - 1 && people < m) { + corn = bus; + } + } + bus = bus.plusMinutes(t); + } + return corn.toString(); + } + + public String solution2(int n, int t, int m, String[] timetable) { + Arrays.sort(timetable); + + LocalTime nextBusTime = LocalTime.parse("09:00", DateTimeFormatter.ofPattern("HH:mm")); + LocalTime lastBusTime = nextBusTime.minusHours(1).plusMinutes(n * t); + System.out.println(lastBusTime); + int crew = 0; + for (String time : timetable) { + System.out.println(nextBusTime + " " + crew); + if (nextBusTime.isAfter(lastBusTime) || nextBusTime.equals(lastBusTime)) { + break; + } + + if (crew > m) { + crew = 0; + continue; + } + + if (nextBusTime.toString().compareTo(time) > 0) { + crew++; + continue; + } + + nextBusTime = nextBusTime.plusMinutes(t); + } + + return lastBusTime.toString(); + } + +} diff --git a/src/delf/programmers/Solution17679.java b/src/delf/programmers/Solution17679.java new file mode 100644 index 0000000..a0a9d97 --- /dev/null +++ b/src/delf/programmers/Solution17679.java @@ -0,0 +1,113 @@ +package programmers; + +import java.util.*; + +/** + * [1차] 프렌즈4블록 + * https://programmers.co.kr/learn/courses/30/lessons/17679 + */ +public class Solution17679 { + public static void main(String[] args) { +// System.out.println(new Solution17679().solution(4, 5, new String[]{"CCBDE", "AAADE", "AAABF", "CCBBF"})); +// System.out.println(new Solution17679().solution(6, 6, new String[]{"TTTANT", "RRFACC", "RRRFCC", "TRRRAA", "TTMMMF", "TMMTTJ"})); +// System.out.println(new Solution17679().solution(6, 6, new String[]{"AABBEE", "AAAEEE", "VAAEEV", "AABBEE", "AACCEE", "VVCCEE"})); +// System.out.println(new Solution17679().solution(2, 2, new String[]{"AA", "AB"})); +// System.out.println(new Solution17679().solution(3, 2, new String[]{"AA", "AA", "AB"})); +// System.out.println(new Solution17679().solution(4, 2, new String[]{"CC", "AA", "AA", "CC"})); + System.out.println(new Solution17679().solution(6, 2, new String[]{"DD", "CC", "AA", "AA", "CC", "DD"})); +// System.out.println(new Solution17679().solution(8, 2, new String[]{"FF", "AA", "CC", "AA", "AA", "CC", "DD", "FF"})); +// System.out.println(new Solution17679().solution(6, 2, new String[]{"AA", "AA", "CC", "AA", "AA", "DD"})); + + + } + + private char[][] chBoard; + int[][] DIR = {{0, 0}, {0, 1}, {1, 0}, {1, 1}}; + + public int solution(int m, int n, String[] board) { + chBoard = new char[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + chBoard[i][j] = board[i].charAt(j); + } + } + + int answer = 0; + Set marker = new LinkedHashSet<>(); // 삭제할 블록 + do { + marker.clear(); + // 스캔 + for (int i = 0; i < m - 1; i++) { + for (int j = 0; j < n - 1; j++) { + if (isWindowBingo(i, j)) { + for (int[] d : DIR) { + marker.add(new Block(i + d[0], j + d[1])); + } + } + } + } + + // 처리 + for (Block block : marker) { + for (int mm = block.m; mm >= 0; mm--) { + if (mm - 1 < 0) { + chBoard[mm][block.n] = '0'; + break; + } + if (chBoard[mm - 1][block.n] != '0') { + chBoard[mm][block.n] = chBoard[mm - 1][block.n]; + } else { + chBoard[mm][block.n] = '0'; + break; + } + } + } + answer += marker.size(); + } while (marker.size() > 0); + + return answer; + } + + private boolean isWindowBingo(int m, int n) { + if (chBoard[m][n] == '0' || chBoard[m][n] != chBoard[m][n + 1]) { + return false; + } + if (chBoard[m][n + 1] == '0' || chBoard[m][n + 1] != chBoard[m + 1][n]) { + return false; + } + return chBoard[m + 1][n] == '0' || chBoard[m + 1][n] == chBoard[m + 1][n + 1]; + } + + static class Block { + int m; + int n; + + public Block(int m, int n) { + this.m = m; + this.n = n; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Block block = (Block) o; + + if (m != block.m) return false; + return n == block.n; + } + + @Override + public int hashCode() { + int result = m; + result = 31 * result + n; + return result; + } + + @Override + public String toString() { + return String.format("(%d, %d)", m, n); + } + } +} \ No newline at end of file diff --git a/src/delf/programmers/Solution17680.java b/src/delf/programmers/Solution17680.java new file mode 100644 index 0000000..c0012d7 --- /dev/null +++ b/src/delf/programmers/Solution17680.java @@ -0,0 +1,59 @@ +package programmers; + +import java.util.*; + +/** + * 캐시 + * https://programmers.co.kr/learn/courses/30/lessons/17680 + */ +public class Solution17680 { + public static void main(String[] args) { + System.out.println(new Solution17680().solution(3, new String[]{"Jeju", "Pangyo", "Seoul", "NewYork", "LA", "Jeju", "Pangyo", "Seoul", "NewYork", "LA"}));//,50 +// System.out.println(new Solution17680().solution(3, new String[]{"Jeju", "Pangyo", "Seoul", "Jeju", "Pangyo", "Seoul", "Jeju", "Pangyo", "Seoul"}));//,21 +// System.out.println(new Solution17680().solution(2, new String[]{"Jeju", "Pangyo", "Seoul", "NewYork", "LA", "SanFrancisco", "Seoul", "Rome", "Paris", "Jeju", "NewYork", "Rome"}));//,60 +// System.out.println(new Solution17680().solution(5, new String[]{"Jeju", "Pangyo", "Seoul", "NewYork", "LA", "SanFrancisco", "Seoul", "Rome", "Paris", "Jeju", "NewYork", "Rome"}));//,52 +// System.out.println(new Solution17680().solution(2, new String[]{"Jeju", "Pangyo", "NewYork", "newyork"}));//,16 + System.out.println(new Solution17680().solution(0, new String[]{"Jeju", "Pangyo", "Seoul", "NewYork", "LA"}));//,25 + +// System.out.println(new Solution17680().solution(2, new String[]{"Jeju", "Jeju", "Jeju", "Jeju", "Jeju"}));//,25 + } + + private final static int HIT = 1; + private final static int MISS = 5; + + public int solution(int cacheSize, String[] cities) { + Queue q = new LinkedList<>(); + + int time = 0; + for (String cityOrigin : cities) { + String city = cityOrigin.toLowerCase(); + System.out.println(city + " " + q); + if (q.contains(city)) { + time += HIT; + q.remove(city); + } else { + time += MISS; + if (q.size() >= cacheSize) { + q.poll(); + } + } + if (q.size() < cacheSize) { + q.add(city); + } + } + return time; + } + + class QueueSet { + private Queue queue; + private T lastData; + private int maxsize; + + public boolean add(T element) { + if (queue.isEmpty()) { + lastData = element; + } + return queue.add(element); + } + } +} diff --git a/src/delf/programmers/Solution17683.java b/src/delf/programmers/Solution17683.java new file mode 100644 index 0000000..1aa5d68 --- /dev/null +++ b/src/delf/programmers/Solution17683.java @@ -0,0 +1,100 @@ +package programmers; + +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * 방금 그곡 + * https://programmers.co.kr/learn/courses/30/lessons/17683 + */ +public class Solution17683 { + private static final Map sharp; + + static { + sharp = new HashMap<>(); + sharp.put("C#", "c"); + sharp.put("D#", "d"); + sharp.put("F#", "f"); + sharp.put("G#", "g"); + sharp.put("A#", "a"); + } + + public String solution(String m, String[] musicinfos) { +// Map playInfo = new LinkedHashMap<>(); + List titles = new ArrayList<>(); + List melodys = new ArrayList<>(); + for (String musicinfo : musicinfos) { + String[] info = musicinfo.split(","); + + int playTime = getPlayTime(info[0], info[1]); + titles.add(info[2]); + melodys.add(getFullPlayNotes(info[3], playTime)); + } + + String convertedMelody = convertSharpNote(m); + int maxMelodyLength = 0; + String maxMelodyTitle = ""; + for (int i = 0; i < titles.size(); i++) { + String melody = melodys.get(i); + if (melody.contains(convertedMelody)) + if (melody.length() > maxMelodyLength) { + maxMelodyLength = melody.length(); + maxMelodyTitle = titles.get(i); + } + } + + return maxMelodyTitle.equals("") ? "(None)" : maxMelodyTitle; + } + + static private int getPlayTime(String start, String end) { + LocalTime startLdt = LocalTime.parse(start, DateTimeFormatter.ofPattern("HH:mm")); + LocalTime endLdt = LocalTime.parse(end, DateTimeFormatter.ofPattern("HH:mm")); + return endLdt.minusMinutes(startLdt.getMinute()).getMinute(); + } + + static private int getTimeDiff(String start, String end) { + String[] startTime = start.split(":"); + String[] endTime = end.split(":"); + + int startMinute = Integer.valueOf(startTime[0]); + int startSecond = Integer.valueOf(startTime[1]); + + int endMinute = Integer.valueOf(endTime[0]); + int endSecond = Integer.valueOf(endTime[1]); + + return (endMinute - startMinute) * 60 + (endSecond - startSecond); + } + + private String getFullPlayNotes(String notes, int playTime) { + StringBuilder fullNotes = new StringBuilder(); + notes = convertSharpNote(notes); + for (int i = 0; i < playTime / notes.length(); i++) { + fullNotes.append(notes); + } + fullNotes.append(notes, 0, playTime % notes.length()); + + return fullNotes.toString(); + } + + + private String convertSharpNote(String notes) { + for (String key : sharp.keySet()) { + notes = notes.replaceAll(key, sharp.get(key)); + } + return notes; + } + + public static void main(String[] args) { +// String s = "ABCDEDHSFWAEFDF"; +// System.out.println(s.indexOf("ABCDEDHSFWAEFDF")); +// System.out.println(new Solution17683().solution("ABC", new String[]{"13:00,13:06,JJ,CCABCD", "13:00,13:06,WORLD,ABCDEF", "12:00,12:14,HELLO,A",})); +// System.out.println(new Solution17683().solution("CC#BCC#BCC#BCC#B", new String[]{"03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"})); +// System.out.println(new Solution17683().solution("ABC", new String[]{"12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,ABCDEF"})); + String start = "11:00"; + String end = "24:00"; + + System.out.println(getPlayTime(start, end)); + System.out.println(getTimeDiff(start, end)); + } +} diff --git a/src/delf/programmers/Solution17684.java b/src/delf/programmers/Solution17684.java new file mode 100644 index 0000000..be0b88a --- /dev/null +++ b/src/delf/programmers/Solution17684.java @@ -0,0 +1,76 @@ +package programmers; + +import java.util.*; + +/** + * [3차] 압축 + * https://programmers.co.kr/learn/courses/30/lessons/17684 + */ +public class Solution17684 { + + public static void main(String[] args) { + System.out.println(DICTIONARY_BASE); + System.out.println(Arrays.toString(new Solution17684().solution("KAKAO"))); + System.out.println(Arrays.toString(new Solution17684().solution("TOBEORNOTTOBEORTOBEORNOT"))); + } + + private final static Map DICTIONARY_BASE = new HashMap<>(); + + static { + for (int i = 0; i < 26; i++) { + DICTIONARY_BASE.put(Character.toString((char) ('A' + i)), i + 1); + } + } + + // 1. key를 기준으로 정렬된 map 생성 (문자열이 길이 내림차순) + // 2. msg가 dictionary의 key로 시작하는지 체크 + // 3. 조건에 맞는 key를 찾으면, 색인을 저장하고 문자열 처리 + // - 문자열 처리: 사전에 'key+다음문자'에 해당하는 문자열 추가, msg에서 key에 해당하는 문자열 삭제 + // 4. 반복 + public int[] solution(String msg) { + + // 1. key를 기준으로 정렬된 map 생성 (문자열이 길이 내림차순) + Map dictionary = new TreeMap<>((o1, o2) -> { + if (o1.length() == o2.length()) { + return o1.compareTo(o2); + } + return o2.length() - o1.length(); + }); + dictionary.putAll(DICTIONARY_BASE); + + + List result = new ArrayList<>(); + while (msg.length() > 0) { + for (String key : dictionary.keySet()) { + // +) 문자열 비교로 중간에 연산 줄일 수 있을 듯 + // 2. msg가 dictionary의 key로 시작하는지 체크 + if (msg.startsWith(key)) { + // 3. 조건에 맞는 key를 찾으면, 색인을 저장하고 문자열 처리 + result.add(dictionary.get(key)); + int length = key.length(); + if (msg.length() > length) { + // 3-1. 'key+다음문자'에 해당하는 문자열 추가 + dictionary.putIfAbsent(msg.substring(0, length + 1), dictionary.size() + 1); + } + // 3-2. msg에서 key에 해당하는 문자열 삭제 + msg = msg.substring(length); + break; + } + } + // 4. 반복 + } + + return result.stream().mapToInt(Integer::intValue).toArray(); + } + + + private Comparator comparator() { + return (o1, o2) -> { + if (o1.length() == o2.length()) { + return o1.compareTo(o2); + } + return o2.length() - o1.length(); + }; + } + +} diff --git a/src/delf/programmers/Solution17686.java b/src/delf/programmers/Solution17686.java new file mode 100644 index 0000000..2ced8b3 --- /dev/null +++ b/src/delf/programmers/Solution17686.java @@ -0,0 +1,83 @@ +package programmers; + +import java.util.*; +import java.util.regex.Pattern; + +/** + * [3차] 파일명 정렬 + * https://programmers.co.kr/learn/courses/30/lessons/17686 + */ +public class Solution17686 { + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution17686().solution(new String[]{"F-5 Freedom Fighter", "B-50 Superfortress", "A-10 Thunderbolt II", "F-14 Tomcat"}))); + System.out.println(Arrays.toString(new Solution17686().solution(new String[]{"a 001.ee", "A1.zz", "a01.33"}))); + System.out.println(new FileName("abc123.jpg")); + + } + + public String[] solution(String[] files) { + String[] answer = new String[files.length]; + FileName[] fileNames = new FileName[files.length]; + for (int i = 0; i < fileNames.length; i++) { + fileNames[i] = new FileName(files[i]); + } + + Arrays.sort(fileNames); + + for (int i = 0; i < fileNames.length; i++) { + answer[i] = fileNames[i].origin; + } + return answer; + } + + static class FileName implements Comparable { + private String origin; + + private String head = ""; + private int number = -1; + + @Override + public String toString() { + return "FileName{" + + "origin='" + origin + '\'' + + ", head='" + head + '\'' + + ", number=" + number + + '}'; + } + + public FileName(String origin) { + this.origin = origin; + + for (int i = 0; i < origin.length(); i++) { + char ch = origin.charAt(i); + + if (head.isEmpty()) { + if (Character.isDigit(ch)) { + head = origin.substring(0, i).toLowerCase(); + } + } else { + if (!Character.isDigit(ch)) { + int endIndex = i - head.length() > 5 ? head.length() + 5 : i; + number = Integer.parseInt(origin.substring(head.length(), endIndex)); + break; + } + } + } + if (number == -1) { + int endIndex = origin.length() - head.length() > 5 ? head.length() + 5 : origin.length(); + number = Integer.parseInt(origin.substring(head.length(), endIndex)); + } + } + + @Override + public int compareTo(FileName o) { + if (this.head.equals(o.head)) { + if (this.number == o.number) { + return 1; + } + return Integer.compare(this.number, o.number); + } + return this.head.compareTo(o.head); + } + } +} diff --git a/src/delf/programmers/Solution1829.java b/src/delf/programmers/Solution1829.java new file mode 100644 index 0000000..7decf92 --- /dev/null +++ b/src/delf/programmers/Solution1829.java @@ -0,0 +1,115 @@ +package programmers; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; + +public class Solution1829 { + + private static final int[][] direction = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + private static final int X = 0; + private static final int Y = 1; + + public int[] solution(int m, int n, int[][] picture) { + boolean[][] visited = new boolean[m][n]; + int numberOfArea = 0; + int maxSizeOfOneArea = 0; + int area; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (picture[i][j] == 0 || visited[i][j]) { + continue; + } + area = bfs(i, j, picture, visited); + numberOfArea++; + if (maxSizeOfOneArea < area) { + maxSizeOfOneArea = area; + } + } + } + return new int[]{numberOfArea, maxSizeOfOneArea}; + } + + private int bfs(int x, int y, int[][] picture, boolean[][] visited) { + int area = 1; + visited[x][y] = true; + + Queue queue = new LinkedList<>(); + queue.add(new Node(x, y)); + + while (!queue.isEmpty()) { + Node now = queue.poll(); + for (int[] d : direction) { + int nx = now.x + d[X]; + int ny = now.y + d[Y]; + + if (nx < 0 || nx >= picture.length || ny < 0 || ny >= picture[0].length) { + continue; + } + if (picture[nx][ny] != picture[x][y] || visited[nx][ny]) { + continue; + } + queue.add(new Node(nx, ny)); + visited[nx][ny] = true; + area++; + } + } + return area; + } + + public class Node { + int x; + int y; + + public Node(int x, int y) { + this.x = x; + this.y = y; + } + } + + public int[] solution2(int m, int n, int[][] picture) { + int numberOfArea = 0; + int maxSizeOfOneArea = 0; + int area = 1; + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (picture[i][j] == 0) { + continue; + } + area = dfs(i, j, picture[i][j], picture); + if (maxSizeOfOneArea < area) { + maxSizeOfOneArea = area; + } + numberOfArea++; + } + } + return new int[]{numberOfArea, maxSizeOfOneArea}; + } + + private int dfs(int x, int y, int prevColor, int[][] picture) { + if (picture[x][y] != prevColor) { + return 0; + } + int count = 1; + picture[x][y] = 0; + for (int[] d : direction) { + int nx = x + d[X]; + int ny = y + d[Y]; + + if (nx < 0 || nx >= picture.length || ny < 0 || ny >= picture[0].length) { + continue; + } + if (picture[nx][ny] != prevColor || picture[nx][ny] == 0) { + continue; + } + + count += dfs(nx, ny, prevColor, picture); + } + return count; + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution1829().solution(6, 4, new int[][]{{1, 1, 1, 0}, {1, 2, 2, 0}, {1, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 3}, {0, 0, 0, 3}}))); + } +} diff --git a/src/delf/programmers/Solution1845.java b/src/delf/programmers/Solution1845.java new file mode 100644 index 0000000..9e6b754 --- /dev/null +++ b/src/delf/programmers/Solution1845.java @@ -0,0 +1,33 @@ +package programmers; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * 폰켓몬 + * https://programmers.co.kr/learn/courses/30/lessons/1845 + */ +public class Solution1845 { + public static void main(String[] args) { + System.out.println(new Solution1845().solution(new int[]{3, 3, 3, 2, 2, 4})); + + } + + public int solution(int[] nums) { + + return Math.min(nums.length / 2, IntStream.of(nums).boxed().collect(Collectors.toCollection(HashSet::new)).size()); + + } + + public int solution2(int[] nums) { + Set set = new HashSet<>(); + + for (int num : nums) { + set.add(num); + } + + return Math.min(nums.length / 2, set.size()); + } +} diff --git a/src/delf/programmers/Solution42628.java b/src/delf/programmers/Solution42628.java new file mode 100644 index 0000000..20233ed --- /dev/null +++ b/src/delf/programmers/Solution42628.java @@ -0,0 +1,49 @@ +package programmers; + +import java.util.Arrays; +import java.util.Collections; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +/** + * 이중 우선순위 큐 + * https://programmers.co.kr/learn/courses/30/lessons/42628 + */ +public class Solution42628 { + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution42628().solution(new String[]{"I 7", "I 5", "I -5", "D -1"}))); + } + + public int[] solution(String[] operations) { + PriorityQueue pq = new PriorityQueue<>(); + PriorityQueue maxPq = new PriorityQueue<>(Collections.reverseOrder()); + + for (String op : operations) { + StringTokenizer st = new StringTokenizer(op); + String judge = st.nextToken(); + int value = Integer.parseInt(st.nextToken()); + + if (pq.size() < 1 && judge.equals("D")) { + continue; + } + + if (judge.equals("I")) { + pq.offer(value); + maxPq.offer(value); + continue; + } + + if (value < 0) { + maxPq.remove(pq.poll()); + continue; + } + + pq.remove(maxPq.poll()); + } + if (pq.size() > 0) { + return new int[]{maxPq.poll(), pq.poll()}; + } + + return new int[]{0, 0}; + } +} diff --git a/src/delf/programmers/Solution42839.java b/src/delf/programmers/Solution42839.java new file mode 100644 index 0000000..ab1c18f --- /dev/null +++ b/src/delf/programmers/Solution42839.java @@ -0,0 +1,89 @@ +package programmers; + + +import java.util.HashSet; +import java.util.Set; + +/** + * 소수찾기 + * https://programmers.co.kr/learn/courses/30/lessons/42839 + */ +public class Solution42839 { + + + public static void main(String[] args) { + System.out.println(new Solution42839().solution("1234")); + } + + public int solution(String numbers) { + Set set = new HashSet<>(); + for (char i : numbers.toCharArray()) { + set.add(i - '0'); + } + + for (int i = 2; i <= numbers.length(); i++) { + set.addAll(new Permutation(numbers, i).getResult()); + } + + int count = 0; + for (int n : set) { + count += isPrime(n) ? 1 : 0; + } + + return count; + } + + + public boolean isPrime(int num) { + if (num <= 1) { + return false; + } + + for (int i = 2; i * i <= num; i++) { + if (num % i == 0) return false; + } + return true; + } + + class Permutation { + + private Set set = new HashSet<>(); + + public Set getResult() { + return set; + } + + public Permutation(String number, int r) { + permutation(number.toCharArray(), 0, number.length(), r); + } + + private void permutation(char[] arr, int depth, int n, int r) { + if (depth == r) { + set.add(arrToInteger(arr, r)); + return; + } + + for (int i = depth; i < n; i++) { + swap(arr, depth, i); + permutation(arr, depth + 1, n, r); + swap(arr, depth, i); + } + } + + private void swap(char[] arr, int depth, int i) { + char temp = arr[depth]; + arr[depth] = arr[i]; + arr[i] = temp; + } + + private int arrToInteger(char[] arr, int r) { + int result = 0; + for (int i = 0; i < r; i++) { + result *= 10; + result += (arr[i] - '0'); + } + return result; + } + } + +} diff --git a/src/delf/programmers/Solution42860.java b/src/delf/programmers/Solution42860.java new file mode 100644 index 0000000..9ba275b --- /dev/null +++ b/src/delf/programmers/Solution42860.java @@ -0,0 +1,52 @@ +package programmers; + +import org.omg.CORBA.MARSHAL; + +import java.util.Arrays; + +/** + * 조이스틱 + * https://programmers.co.kr/learn/courses/30/lessons/42860 + * 틀린 풀이 + * 참고: https://keepgoing0328.tistory.com/71 + */ +public class Solution42860 { + public int solution(String name) { + char[] arr = name.toCharArray(); + int moveCnt = 0; + int index = 0; + while (true) { + int inc = getInc(index, arr); + if (Math.abs(inc) >= arr.length) { + break; + } + moveCnt += ((Math.min(arr[index] - 'A', Math.abs('Z' - arr[index] + 1))) + Math.abs(inc)); + arr[index] = 'A'; + index = inc >= 0 ? (index + inc) % arr.length : (index + inc +arr.length) % arr.length; + } + return moveCnt; + } + + private int getInc(int index, char[] arr) { + int right; + for (right = 0; right < arr.length; right++) { + if (arr[(index + right) % arr.length] != 'A') { + break; + } + } + int left; + for (left = 0; left < arr.length; left++) { + if (arr[(index - left + arr.length) % arr.length] != 'A') { + break; + } + } + return right < left ? right : -left; + } + + public static void main(String[] args) { +// System.out.println(new Solution42860().solution("AABAAAAAAAB")); +// System.out.println(new Solution42860().solution("JEROEN")); + System.out.println(new Solution42860().solution("AAZAAAZ")); + + } +} diff --git a/src/delf/programmers/Solution42860_2.java b/src/delf/programmers/Solution42860_2.java new file mode 100644 index 0000000..d2002a3 --- /dev/null +++ b/src/delf/programmers/Solution42860_2.java @@ -0,0 +1,45 @@ +package programmers; + +/** + * @author delf + */ +public class Solution42860_2 { + public static void main(String[] args) { +// System.out.println(new Solution42860().solution("AABAAAAAAAB")); +// System.out.println(new Solution42860().solution("JEROEN")); + System.out.println(">>>>>> " + new Solution42860_2().solution("BBBBAAAABA")); + System.out.println(">>>>>> " + new Solution42860_2().solution("BBBBAAAAAB")); + System.out.println(">>>>>> " + new Solution42860_2().solution("AABAAAAAAABBB")); + System.out.println(">>>>>> " + new Solution42860_2().solution("AAB")); + System.out.println(">>>>>> " + new Solution42860_2().solution("CANAAAAANAN")); + } + + public int solution(String name) { + return recursive(name.toCharArray(), 0); + } + + private int recursive(char[] name, int index) { + char[] arr = name.clone(); + int upDownCnt = Math.min(arr[index] - 'A', Math.abs('Z' - arr[index] + 1)); + arr[index] = 'A'; + + int right = 0; + for (int i = 1; i < arr.length; i++) { + int ci = (index + i) < arr.length ? index + i : (index + i) % arr.length; + if (arr[ci] != 'A') { + right += (recursive(arr, ci) + i); + break; + } + } + + int left = 0; + for (int i = 1; i < arr.length; i++) { + int ci = (index - i) < 0 ? (index - i + arr.length) % arr.length : index - i; + if (arr[ci] != 'A') { + left += (recursive(arr, ci) + i); + break; + } + } + return Math.min(left, right) + upDownCnt; + } +} diff --git a/src/delf/programmers/Solution42861.java b/src/delf/programmers/Solution42861.java new file mode 100644 index 0000000..ddcef07 --- /dev/null +++ b/src/delf/programmers/Solution42861.java @@ -0,0 +1,62 @@ +package programmers; + +import java.util.Arrays; + +/** + * 섬 연결하기 + * https://programmers.co.kr/learn/courses/30/lessons/42861 + */ +public class Solution42861 { + private int[][] graph; + private boolean[][] isVisit; + + public int solution(int n, int[][] costs) { + graph = new int[n][n]; + for (int[] cost : costs) { + setCost(cost[0], cost[1], cost[2]); + } + System.out.println(Arrays.deepToString(graph)); + + isVisit = new boolean[n][n]; + + return dfs(0, 0, 0); + } + + private int dfs(int from, int to, int depth) { + visit(from, to); + + if (depth == graph.length) { + return graph[from][to]; + } + + int min = graph[from][to]; + for (int i = 0; i < graph.length; i++) { + if (i == to) { + continue; + } + if (isVisit[to][i] || graph[to][i] == 0) { + continue; + } + + int cost = dfs(to, i, depth + 1); + min += Math.min(cost, min); + } + + return min; + } + + private void visit(int from, int to) { + isVisit[from][to] = true; + isVisit[to][from] = true; + } + + private void setCost(int from, int to, int cost) { + graph[from][to] = cost; + graph[to][from] = cost; + } + + public static void main(String[] args) { + System.out.println(new Solution42861().solution(4, new int[][]{{0, 1, 1}, {0, 2, 2}, {1, 2, 5}, {1, 3, 1}, {2, 3, 8}})); + } +} + diff --git a/src/delf/programmers/Solution42885.java b/src/delf/programmers/Solution42885.java new file mode 100644 index 0000000..63923b8 --- /dev/null +++ b/src/delf/programmers/Solution42885.java @@ -0,0 +1,35 @@ +package programmers; + +import java.util.Arrays; +import java.util.Collections; + +/** + * 구명보트 + * https://programmers.co.kr/learn/courses/30/lessons/42885 + */ +public class Solution42885 { + public static void main(String[] args) { + System.out.println(new Solution42885().solution(new int[]{70, 50, 80, 50}, 100)); + } + + public int solution(int[] people, int limit) { + int answer = 0; + + Arrays.sort(people); + System.out.println(Arrays.toString(people)); + int left = 0; + int right = people.length - 1; + + while (left <= right) { + int weight = people[left] + people[right]; + if (weight > limit) { + right--; + } else { + left++; + right--; + } + answer++; + } + return answer; + } +} diff --git a/src/delf/programmers/Solution42888.java b/src/delf/programmers/Solution42888.java new file mode 100644 index 0000000..5f6ff25 --- /dev/null +++ b/src/delf/programmers/Solution42888.java @@ -0,0 +1,55 @@ +package programmers; + +import java.util.*; + +/** + * 오픈 채팅방 + * https://programmers.co.kr/learn/courses/30/lessons/42888 + */ +public class Solution42888 { + + public static void main(String[] args) { + StringBuilder sb = new StringBuilder("abc"); + System.out.println(sb.replace(1, 2, "s").toString()); + + +// System.out.println(Arrays.toString(new Solution42888().solution(new String[]{"Enter uid1234 Muzi", "Enter uid4567 Prodo", "Leave uid1234", "Enter uid1234 Prodo", "Change uid4567 Ryan"}))); + } + + private final static String ENTER_LOG_FORMAT = "%s님이 들어왔습니다."; + private final static String LEAVE_LOG_FORMAT = "%s님이 나갔습니다."; + + private final Map map = new HashMap<>(); + + public String[] solution(String[] record) { + List answer = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + + sb.replace(1, 2, "S"); + + + for (String value : record) { + String[] split = value.split(" "); + switch (split[0]) { + case "Enter": + case "Change": + map.put(split[1], split[2]); + break; + } + } + + for (String s : record) { + String[] split = s.split(" "); + switch (split[0]) { + case "Enter": + answer.add(String.format(ENTER_LOG_FORMAT, map.get(split[1]))); + break; + case "Leave": + answer.add(String.format(LEAVE_LOG_FORMAT, map.get(split[1]))); + break; + } + } + + return answer.toArray(new String[0]); + } +} diff --git a/src/delf/programmers/Solution42890.java b/src/delf/programmers/Solution42890.java new file mode 100644 index 0000000..da8374d --- /dev/null +++ b/src/delf/programmers/Solution42890.java @@ -0,0 +1,70 @@ +package programmers; + +import java.util.*; +/** + * 후보키 + * https://programmers.co.kr/learn/courses/30/lessons/42890 + * */ +public class Solution42890 { + public static void main(String[] args) { + System.out.println(new Solution42890().solution(new String[][]{{"100", "ryan", "music", "2"}, {"200", "apeach", "math", "2"}, {"300", "tube", "computer", "3"}, {"400", "con", "computer", "4"}, {"500", "muzi", "music", "3"}, {"600", "apeach", "music", "2"}})); + } + + private List> candidate = new ArrayList<>(); + + public int solution(String[][] relation) { + boolean[] isVisit = new boolean[relation[0].length]; + dfs(0, isVisit, relation); + return candidate.size(); + } + + private void dfs(int index, boolean[] isVisit, String[][] relation) { + if (isVisit.length == index) { // 조건 만족 + Set subset = getSubset(isVisit); + if (!subset.isEmpty() && isMinimal(subset) && isUnique(isVisit, relation)) { + candidate.add(subset); + } + return; + } + + isVisit[index] = false; // 자신 포함 X + dfs(index + 1, isVisit, relation); + isVisit[index] = true; // 자신 포함 O + dfs(index + 1, isVisit, relation); + } + + private boolean isMinimal(Set set) { + for (Set c : candidate) { + if (set.containsAll(c)) { + return false; + } + } + return true; + } + + private boolean isUnique(boolean[] isVisit, String[][] relation) { + Set dupChecker = new HashSet<>(); + for (String[] col : relation) { + StringBuilder tmp = new StringBuilder(); + for (int j = 0; j < isVisit.length; j++) { + if (isVisit[j]) { + tmp.append(col[j]); + } + } + if (!tmp.toString().equals("") && !dupChecker.add(tmp.toString())) { + return false; + } + } + return true; + } + + private Set getSubset(boolean[] isVisit) { + Set set = new HashSet<>(); + for (int i = 0; i < isVisit.length; i++) { + if (isVisit[i]) { + set.add(i); + } + } + return set; + } +} \ No newline at end of file diff --git a/src/delf/programmers/Solution42892.java b/src/delf/programmers/Solution42892.java new file mode 100644 index 0000000..02592a0 --- /dev/null +++ b/src/delf/programmers/Solution42892.java @@ -0,0 +1,110 @@ +package programmers; + +import java.util.*; + +/** + * 길 찾기 게임 + * https://programmers.co.kr/learn/courses/30/lessons/42892 + */ +public class Solution42892 { + static int X = 0; + static int Y = 1; + + public static void main(String[] args) { + System.out.println(Arrays.deepToString(solution(new int[][]{{5, 3}, {11, 5}, {13, 3}, {3, 5}, {6, 1}, {1, 3}, {8, 6}, {7, 2}, {2, 2}}))); + } + + public static int[][] solution(int[][] nodeinfo) { + List nodeList = new ArrayList<>(); + for (int i = 0; i < nodeinfo.length; i++) { + Node node = new Node(i + 1, nodeinfo[i][X], nodeinfo[i][Y]); + nodeList.add(node); + } + + Collections.sort(nodeList); + System.out.println(nodeList); + + Node parent = nodeList.get(0); + Node head = parent; + Node grandParent; + Node firstNodeAtLevel = head; + for (int i = 1; i < nodeinfo.length; i++) { + Node node = nodeList.get(i); + if (firstNodeAtLevel.y != node.y) { + parent = firstNodeAtLevel; + firstNodeAtLevel = node; + } + + // 왼쪽의 왼쪽 + if (node.x < parent.x) { + parent.left = node; + node.parent = parent; + continue; + } + + // 왼쪽의 오른쪽 + grandParent = parent.parent; + if (grandParent == null || node.x < grandParent.x) { + parent.right = node; + node.parent = parent; + continue; + } + + Node sibling = grandParent.right; + if (node.x < sibling.x) { // 오른쪽의 왼쪽 + sibling.left = node; + } else { // 오른쪽의 오른쪽 + sibling.right = node; + } + node.parent = sibling; + } + printPreOrder(head); + return new int[1][1]; + } + + static void printPreOrder(Node node) { + System.out.println(node.value); + printPreOrder(node.left); + printPreOrder(node.right); + } + + static void printPostOrder(Node node) { + printPreOrder(node.left); + System.out.println(node.value); + printPreOrder(node.right); + } + + static class Node implements Comparable { + int value; + int x; + int y; + Node parent; + Node left; + Node right; + + public Node(int value, int x, int y) { + this.value = value; + this.x = x; + this.y = y; + } + + @Override + public String toString() { + return "Node{" + + "value=" + value + + ", x=" + x + + ", y=" + y + + ", left.v=" + (left == null ? "null" : left.value) + + ", right.v=" + (right == null ? "null" : right.value) + + "}\n"; + } + + @Override + public int compareTo(Node o) { + if (this.y == o.y) { + return this.x - o.x; + } + return o.y - this.y; + } + } +} diff --git a/src/delf/programmers/Solution42895.java b/src/delf/programmers/Solution42895.java new file mode 100644 index 0000000..134372c --- /dev/null +++ b/src/delf/programmers/Solution42895.java @@ -0,0 +1,62 @@ +package programmers; + +import java.util.*; + +/** + * N으로 표현 + * https://programmers.co.kr/learn/courses/30/lessons/42895 + */ +public class Solution42895 { + private final static int MAX = 8; + + public static int solution(int n, int num) { + List> sets = new ArrayList<>(); + + for (int i = 0; i < MAX; i++) { + Set set = new HashSet<>(); + set.add(repeatIntegerN(n, i + 1)); + sets.add(set); + } + + for (int i = 0; i < sets.size(); i++) { + for (int j = 0; j < i; j++) { + for (int op1 : sets.get(j)) { + for (int op2 : sets.get(i - j - 1)) { + sets.get(i).add(op1 + op2); + sets.get(i).add(op1 - op2); + sets.get(i).add(op1 * op2); + if (op2 != 0) { + sets.get(i).add(op1 / op2); + } + } + } + } + if (sets.get(i).contains(num)) { + return i + 1; + } + } + return -1; + } + + private static int repeatIntegerN(int n, int repeat) { + int result = 0; + while (repeat-- > 0) { + result *= 10; + result += n; + } + return result; + } + + public static void main(String[] args) { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + if (j + i != 3) { + continue; + } + System.out.println(i + " " + j); + } + System.out.println(); + } + System.out.println(solution(5, 12)); + } +} diff --git a/src/delf/programmers/Solution42898.java b/src/delf/programmers/Solution42898.java new file mode 100644 index 0000000..ae2b89f --- /dev/null +++ b/src/delf/programmers/Solution42898.java @@ -0,0 +1,30 @@ +package programmers; + +/** + * 등굣길 + * https://programmers.co.kr/learn/courses/30/lessons/42898 + **/ +public class Solution42898 { + public static void main(String[] args) { +// System.out.println(new Solution42898().solution(4, 3, new int[][]{{2, 2}})); + System.out.println(new Solution42898().solution(100, 100, new int[][]{{0, 2}, {1, 2}, {1, 3}, {1, 4}})); + } + + public int solution(int m, int n, int[][] puddles) { + int[][] puddleMap = new int[n + 1][m + 1]; + int[][] dp = new int[n + 1][m + 1]; + for (int[] puddle : puddles) { + puddleMap[puddle[1]][puddle[0]] = -1; + } + dp[1][1] = 1; + for (int i = 1; i < n + 1; i++) { + for (int j = 1; j < m + 1; j++) { + if ((i == 1 && j == 1) || puddleMap[i][j] == -1) { + continue; + } + dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % 1_000_000_007; + } + } + return dp[n][m]; + } +} diff --git a/src/delf/programmers/Solution43162.java b/src/delf/programmers/Solution43162.java new file mode 100644 index 0000000..1191d2e --- /dev/null +++ b/src/delf/programmers/Solution43162.java @@ -0,0 +1,42 @@ +package programmers; + +/** + * 네트워크 + * https://programmers.co.kr/learn/courses/30/lessons/43162 + */ +public class Solution43162 { + private final static int CONNECTED = 1; + + public int solution(int n, int[][] computers) { + boolean[] visit = new boolean[n]; + int result = 0; + for (int i = 0; i < n; i++) { + if (!visit[i]) { + dfs(i, visit, computers); + result++; + } + } + return result; + } + + public void dfs(int node, boolean[] visit, int[][] computers) { + if (visit[node]) { + return; + } + + visit[node] = true; + for (int i = 0; i < visit.length; i++) { + if (node != i && isConnected(node, i, computers)) { + dfs(i, visit, computers); + visit[i] = true; + } + } + } + + public static boolean isConnected(int v1, int v2, int[][] computers) { + if (computers[v1][v2] != CONNECTED) { + return false; + } + return computers[v1][v2] == computers[v2][v1]; + } +} diff --git a/src/delf/programmers/Solution43163.java b/src/delf/programmers/Solution43163.java new file mode 100644 index 0000000..8c8b191 --- /dev/null +++ b/src/delf/programmers/Solution43163.java @@ -0,0 +1,52 @@ +package programmers; + +/** + * 단어 변환 + * https://programmers.co.kr/learn/courses/30/lessons/43163 + */ +public class Solution43163 { + private String[] words; + + public int solution(String begin, String target, String[] words) { + this.words = words;//new ArrayList<>(Arrays.asList(words)); + boolean[] isVisit = new boolean[words.length]; + return dfs(begin, target, isVisit, 0); + } + + + private int dfs(String begin, String target, boolean[] isVisit, int depth) { + if (begin.equals(target)) { + return 0; + } + + int min = words.length; + for (int i = 0; i < words.length; i++) { + if(isVisit[i]) { + continue; + } + + if (hasNext(begin, words[i])) { +// System.out.println(begin + " -> " + words[i]); + isVisit[i] = true; + int tmp = dfs(words[i], target, isVisit, depth); + isVisit[i] = false; + min = Math.min(min, tmp + 1); + } + } + + return min; + } + + private boolean hasNext(String begin, String target) { + boolean hasNext = false; + for (int i = 0; i < begin.length(); i++) { + if (begin.charAt(i) != target.charAt(i)) { + if (hasNext) { + return false; + } + hasNext = true; + } + } + return hasNext; + } +} diff --git a/src/delf/programmers/Solution43164.java b/src/delf/programmers/Solution43164.java new file mode 100644 index 0000000..31dc7ba --- /dev/null +++ b/src/delf/programmers/Solution43164.java @@ -0,0 +1,53 @@ +package programmers; + +import java.util.*; + +/** + * 여행경로 + * https://programmers.co.kr/learn/courses/30/lessons/43164 + */ +public class Solution43164 { + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution43164().solution(new String[][]{{"ICN", "SFO"}, {"ICN", "ATL"}, {"SFO", "ATL"}, {"ATL", "ICN"}, {"ATL", "SFO"}}))); + } + + private List list = new ArrayList<>(); + private String route = ""; + private boolean[] isVisit; + + public String[] solution(String[][] tickets) { + for (int i = 0; i < tickets.length; i++) { + isVisit = new boolean[tickets.length]; + String start = tickets[i][0], end = tickets[i][1]; + + if (start.equals("ICN")) { + route = start + ","; + isVisit[i] = true; + dfs(tickets, end, 1); + } + } + + Collections.sort(list); + + return list.get(0).split(","); + } + + private void dfs(String[][] tickets, String end, int cnt) { + route += end + ","; + + if (cnt == tickets.length) { + list.add(route); + return; + } + + for (int i = 0; i < tickets.length; i++) { + String s = tickets[i][0], e = tickets[i][1]; + if (s.equals(end) && !isVisit[i]) { + isVisit[i] = true; + dfs(tickets, e, cnt + 1); + isVisit[i] = false; + route = route.substring(0, route.length() - 4); + } + } + } +} diff --git a/src/delf/programmers/Solution43165.java b/src/delf/programmers/Solution43165.java new file mode 100644 index 0000000..6372075 --- /dev/null +++ b/src/delf/programmers/Solution43165.java @@ -0,0 +1,26 @@ +package programmers; + +/** + * 타겟 넘버 + * https://programmers.co.kr/learn/courses/30/lessons/43165 + */ +public class Solution43165 { + public static void main(String[] args) { + System.out.println(new Solution43165().solution(new int[]{1, 1, 1, 1, 1}, 3)); + } + + public int solution(int[] numbers, int target) { + return dfs(numbers, target, 0, 0, 0); + } + + private int dfs(int[] numbers, int target, int depth, int sum, int count) { + if (depth == numbers.length) { + if (sum == target) { + count++; + } + return count; + } + return dfs(numbers, target, depth + 1, sum + numbers[depth], count) + + dfs(numbers, target, depth + 1, sum - numbers[depth], count); + } +} diff --git a/src/delf/programmers/Solution43238.java b/src/delf/programmers/Solution43238.java new file mode 100644 index 0000000..bfbad6f --- /dev/null +++ b/src/delf/programmers/Solution43238.java @@ -0,0 +1,35 @@ +package programmers; + +import java.util.Arrays; + +/** + * 입국 심사 + * https://programmers.co.kr/learn/courses/30/lessons/43238 + */ +public class Solution43238 { + public long solution(int n, int[] times) { + Arrays.sort(times); + + long left = 1; + long right = times[times.length - 1] * (long) n; + long answer = right; + + while (left <= right) { + long mid = (left + right) / 2; + long sum = 0; + for (long time : times) { + sum += (mid / time); + } + + if (sum < n) { + left = mid + 1; + } else { + if (mid <= answer) { + answer = mid; + } + right = mid - 1; + } + } + return answer; + } +} diff --git a/src/delf/programmers/Solution49189.java b/src/delf/programmers/Solution49189.java new file mode 100644 index 0000000..ad14237 --- /dev/null +++ b/src/delf/programmers/Solution49189.java @@ -0,0 +1,43 @@ +package programmers; + +import java.util.LinkedList; +import java.util.Queue; + +public class Solution49189 { + public static void main(String[] args) { + System.out.println(new Solution49189().solution(6, new int[][]{{3, 6}, {4, 3}, {3, 2}, {1, 3}, {1, 2}, {2, 4}, {5, 2}})); + } + + public int solution(int n, int[][] edge) { + int[] dist = new int[n + 1]; + boolean[][] map = new boolean[n + 1][n + 1]; + for (int[] i : edge) { + map[i[0]][i[1]] = true; + map[i[1]][i[0]] = true; + } + + Queue nodes = new LinkedList<>(); + nodes.add(1); + + int max = 0; + while (!nodes.isEmpty()) { + int i = nodes.poll(); + + for (int j = 2; j <= n; j++) { + if (dist[j] == 0 && map[i][j]) { + dist[j] = dist[i] + 1; + nodes.add(j); + max = Math.max(max, dist[j]); + } + } + } + + int count = 0; + for (int d : dist) { + if (max == d) + count++; + } + + return count; + } +} diff --git a/src/delf/programmers/Solution49191.java b/src/delf/programmers/Solution49191.java new file mode 100644 index 0000000..1a779b0 --- /dev/null +++ b/src/delf/programmers/Solution49191.java @@ -0,0 +1,49 @@ +package programmers; + +/** + * 순위 + * https://programmers.co.kr/learn/courses/30/lessons/49191 + */ +public class Solution49191 { + public int solution(int n, int[][] results) { + int answer = 0; + int max = Integer.MAX_VALUE; + int[][] m = new int[n + 1][n + 1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + m[i][j] = max; + } + } + + for (int[] e : results) { + m[e[0]][e[1]] = 1; + } + + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + if (m[i][j] > m[i][k] + m[k][j]) { + m[i][j] = m[i][k] + m[k][j]; + } + } + } + } + + for (int i = 1; i <= n; i++) { + boolean flag = true; + for (int j = 1; j <= n; j++) { + if (i == j) { + continue; + } + if (m[i][j] == max && m[j][i] == max) { + flag = false; + break; + } + } + + answer += (flag ? 1 : 0); + } + return answer; + } + +} diff --git a/src/delf/programmers/Solution60057.java b/src/delf/programmers/Solution60057.java new file mode 100644 index 0000000..8ba8d9e --- /dev/null +++ b/src/delf/programmers/Solution60057.java @@ -0,0 +1,45 @@ +package programmers; + +/** + * 문자열 압축 + * https://programmers.co.kr/learn/courses/30/lessons/60057 + */ +public class Solution60057 { + + public static void main(String[] args) { +// System.out.println(new Solution60057().solution("abcabcabcabcdededededede")); + System.out.println(new Solution60057().solution("abcabcdede")); + + } + + public int solution(String s) { + int answer = s.length(); + for (int i = 1; i <= s.length() / 2; i++) { // 반복은 최대 length/2 + String result = press(s, i); + answer = Math.min(answer, result.length()); + } + + return Math.min(answer, press(s, s.length()).length()); // 반복이 없는 경우 = 반복 문자열이 자기 자신(전체) 하나인 경우 + } + + private static String press(String s, int n) { + StringBuilder sb = new StringBuilder(); // 성능을 고려해야했다면, 쓰지 않았을 것 (숫자만 카운팅) + for (int i = 0; i <= s.length() - n; i += n) { + String target = s.substring(i, i + n); // 성능을 고려해야했다면, 쓰지 않았을 것 (캐릭터 단위로 직접비교) + int count = 1; + for (int j = i + n; j <= s.length() - n; j += n) { + if (!target.equals(s.substring(j, j + n))) { + break; + } + i = j; // 비교하는 문자가 같다면, 다음 target 재설정 + count++; + } + if (count > 1) { + sb.append(count); // 반복이 존재하면 숫자 붙이고 + } + sb.append(target); // 해당 문자열 붙이기 + } + sb.append(s.substring(s.length() - (s.length() % n))); + return sb.toString(); + } +} diff --git a/src/delf/programmers/Solution60059.java b/src/delf/programmers/Solution60059.java new file mode 100644 index 0000000..873114e --- /dev/null +++ b/src/delf/programmers/Solution60059.java @@ -0,0 +1,88 @@ +package programmers; + +import java.security.acl.LastOwnerException; + +/** + * 자물쇠와 열쇠 + * https://programmers.co.kr/learn/courses/30/lessons/60059 + */ +public class Solution60059 { + public static void main(String[] args) { + int[][] key = new int[][]{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}; + int[][] lock = new int[][]{{1, 1, 1, 1}, {1, 1, 0, 1}, {1, 0, 1, 1}}; + + System.out.println(new Solution60059().solution3(key, lock)); + } + + + private int lockHole; + + public boolean solution3(int[][] key, int[][] lock) { + boolean[][] bKey = new boolean[key.length][key.length]; + boolean[][] bLock = new boolean[lock.length][lock.length]; + + for (int i = 0; i < lock.length; i++) { + for (int j = 0; j < lock.length; j++) { + if (lock[i][j] == 1) { + bLock[i][j] = true; + } else { + lockHole++; + } + } + } + + for (int i = 0; i < key.length; i++) { + for (int j = 0; j < key.length; j++) { + bKey[i][j] = key[i][j] == 1; + } + } + + int n = lock.length + key.length - 1; + + boolean[][] rotatedKey = bKey; + for (int d = 0; d < 4; d++) { + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (fit(i - (key.length - 1), j - (key.length - 1), rotatedKey, bLock)) { + return true; + } + } + } + rotatedKey = rotate(rotatedKey); + } + return false; + } + + private boolean[][] rotate(boolean[][] key) { + boolean[][] tmp = new boolean[key.length][key.length]; + for (int i = 0; i < key.length; i++) { + for (int j = 0; j < key.length; j++) { + tmp[i][j] = key[j][key.length - (1 + i)]; + } + } + return tmp; + } + + private boolean fit(int ii, int jj, boolean[][] rotatedKey, boolean[][] lock) { + int n = rotatedKey.length; + int cnt = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (ii + i < 0 || ii + i >= lock.length || jj + j < 0 || jj + j >= lock.length) { + continue; + } + boolean k = rotatedKey[i][j]; + boolean l = lock[ii + i][jj + j]; + if (k && l) { // k = true, l = true + return false; + } + if (k) { // k = true, l = false + cnt++; + } + // k = false, l = true + // k = false, l = false + } + } + return cnt == lockHole; + } +} diff --git a/src/delf/programmers/Solution62048.java b/src/delf/programmers/Solution62048.java new file mode 100644 index 0000000..95cef02 --- /dev/null +++ b/src/delf/programmers/Solution62048.java @@ -0,0 +1,20 @@ +package programmers; + +public class Solution62048 { + public static void main(String[] args) { + System.out.println(new Solution62048().solution(8, 12)); + } + + public long solution(int w, int h) { + return ((long) w * (long) h) - ((long) w + (long) h - getGcd(w, h)); + } + + private long getGcd(long a, long b) { + while (b != 0) { + long temp = a % b; + a = b; + b = temp; + } + return Math.abs(a); + } +} diff --git a/src/delf/programmers/Solution64062.java b/src/delf/programmers/Solution64062.java new file mode 100644 index 0000000..be989cb --- /dev/null +++ b/src/delf/programmers/Solution64062.java @@ -0,0 +1,128 @@ +package programmers; + + +import java.util.Arrays; +import java.util.function.BiFunction; + +/** + * 징검다리 건너기 + * https://programmers.co.kr/learn/courses/30/lessons/64062 + */ +public class Solution64062 { + private final static int MAX = 200_000_000; + + public int solution3(int[] stones, int k) { + int[] gapsOfInterval = new int[stones.length - (k - 1)]; + int[] maxValueOfInterval = new int[stones.length - (k - 1)]; + for (int i = 0; i < stones.length - (k - 1); i++) { + gapsOfInterval[i] = getGapOfInterval(stones, i, k, maxValueOfInterval); + } + System.out.println(Arrays.toString(gapsOfInterval)); + System.out.println(Arrays.toString(maxValueOfInterval)); + int minGap = Integer.MAX_VALUE;// IntStream.of(gapsOfInterval).min().orElseThrow(IllegalAccessError::new); + for (int n : gapsOfInterval) { + minGap = Math.min(minGap, n); + } + + int result = Integer.MAX_VALUE; + for (int i = 0; i < gapsOfInterval.length; i++) { + if (gapsOfInterval[i] == minGap) { + result = Math.min(maxValueOfInterval[i], result); + } + } + + return result; + } + + private int getGapOfInterval(int[] arr, int startIdx, int size, int[] maxValueOfInterval) { + int max = arr[startIdx]; + int min = arr[startIdx]; + for (int i = startIdx; i < startIdx + size; i++) { + max = Math.max(max, arr[i]); + min = Math.min(min, arr[i]); + } + maxValueOfInterval[startIdx] = max; + return max - min; + } + + private int getFuncBetween(BiFunction func, int[] arr, int startIdx, int size) { + int result = arr[startIdx]; + for (int i = startIdx + 1; i <= startIdx + size; i++) { + result = func.apply(result, arr[i]); + } + return result; + } + + + public int solution2(int[] stones, int k) { + + int[] nextStone = new int[stones.length]; + for (int crossFriends = 0; crossFriends < MAX; crossFriends++) { + for (int i = 0, distance = 0; i < stones.length; i++) { + if (nextStone[i] >= k) { + return crossFriends; + } + + if (stones[i] > 0) { + stones[i]--; + } + + if (stones[i] == 0) { + distance++; + } else { + distance = 0; + } + nextStone[i] = distance; + } + } + + throw new IllegalArgumentException(); + } + + public int solution(int[] rocks, int distance) { + // 이분탐색은 오름차순으로 정렬되어있는 경우를 전제로한다. + Arrays.sort(rocks); + return binerySearch(distance, rocks, rocks.length); + } + + int binerySearch(int distance, int[] rocks, int n) { + long ans = 0; + long left = 1, right = distance, mid = 0; + + while (left <= right) { + int cnt = 0; + int prev = 0; + mid = (left + right) / 2; + + for (int i = 0; i < rocks.length; ++i) { + if (rocks[i] - prev < mid) { + // mid보다 작은 값이 존재한다는 뜻으로 + // 해당 돌을 제거한다. + cnt++; + } else { + // mid보다 크거나 같은 값이 존재하므로 + // prev를 현재 돌로 초기화한다. + prev = rocks[i]; + } + } + + // 마지막 돌과 도착점 사이의 거리도 확인한다. + if (distance - prev < mid) cnt++; + + if (cnt <= n) { + // 주어진 n 보다 작거나 같은 만큼 돌을 없애서 + // 최솟값 x를 만들 수 있다. + ans = mid > ans ? mid : ans; + left = mid + 1; + } else { + right = mid - 1; + } + } + return (int) ans; + } + + public static void main(String[] args) { +// System.out.println(new Solution64062().solution(new int[]{2, 4, 5, 3, 2, 1, 4, 2, 5, 1}, 3)); + System.out.println(new Solution64062().solution(new int[]{2, 3, 2, 2, 1, 0, 2}, 3)); + } +} diff --git a/src/delf/programmers/Solution64064.java b/src/delf/programmers/Solution64064.java new file mode 100644 index 0000000..e60c4ec --- /dev/null +++ b/src/delf/programmers/Solution64064.java @@ -0,0 +1,41 @@ +package programmers; + +import java.util.HashSet; +import java.util.Set; + +/** + * 불량 사용자 + * https://programmers.co.kr/learn/courses/30/lessons/64064 + */ +public class Solution64064 { + private Set set = new HashSet<>(); + + public int solution(String[] userId, String[] bannedId) { + dfs(0, "", userId, bannedId, new boolean[userId.length]); + return set.size(); + } + + public void dfs(int idx, String s, String[] userId, String[] bannedId, boolean[] visited) { + if (idx == bannedId.length) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < userId.length; i++) { + if (s.contains(String.valueOf(i))) sb.append(i); + } + set.add(sb.toString()); + return; + } + + for (int i = 0; i < userId.length; i++) { + if (visited[i]) { + continue; + } + + String regex = bannedId[idx].replace("*", "."); + if (userId[i].matches(regex)) { + visited[i] = true; + dfs(idx + 1, s + i, userId, bannedId, visited); + visited[i] = false; + } + } + } +} diff --git a/src/delf/programmers/Solution64065.java b/src/delf/programmers/Solution64065.java new file mode 100644 index 0000000..4cbedd2 --- /dev/null +++ b/src/delf/programmers/Solution64065.java @@ -0,0 +1,39 @@ +package programmers; + +import java.util.*; + +import static java.util.stream.Collectors.toList; + +/** + * 튜플 + * https://programmers.co.kr/learn/courses/30/lessons/64065 + */ +public class Solution64065 { + public int[] solution(String input) { + List> list = new ArrayList<>(); + + input = input.substring(2, input.length() - 2); + String[] arr = input.split("},\\{"); + for (String s : arr) { + list.add(Arrays.stream(s.split(",")).map(Integer::parseInt).collect(toList())); + } + + list.sort(Comparator.comparingInt(List::size)); + + int[] result = new int[list.size()]; + Set set = new HashSet<>(); + int cursor = 0; + for (List l : list) { + for (int n : l) { + if (set.contains(n)) { + continue; + } + set.add(n); + result[cursor++] = n; + break; + } + } + + return result; + } +} \ No newline at end of file diff --git a/src/delf/programmers/Solution67257.java b/src/delf/programmers/Solution67257.java new file mode 100644 index 0000000..2b8f93f --- /dev/null +++ b/src/delf/programmers/Solution67257.java @@ -0,0 +1,74 @@ +package programmers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +/** + * 수식 최대화 + * https://programmers.co.kr/learn/courses/30/lessons/67257 + */ +public class Solution67257 { + public static void main(String[] args) { + System.out.println(new Solution67257().solution("100-200*300-500+20")); + System.out.println(new Solution67257().solution("50*6-3*2")); + } + + private List numbers; + private List operator = new ArrayList<>(); + + public long solution(String expression) { + String[] tmp = expression.split("[+*\\-]"); + numbers = Arrays.stream(tmp).mapToLong(Long::parseLong).boxed().collect(toList()); + + int cursor = 0; + for (int i = 0; i < numbers.size() - 1; i++, cursor++) { + cursor += tmp[i].length(); + operator.add(expression.charAt(cursor)); + } + + String[] priorities = {"+*-", "+-*", "*+-", "*-+", "-+*", "-*+"}; + + long max = 0; + for (String priority : priorities) { + long value = calcValueByPriority(priority); + max = Math.max(max, Math.abs(value)); + } + + return max; + } + + private long calcValueByPriority(String priority) { + List tmpNumbers = new ArrayList<>(numbers); + List tmpOperator = new ArrayList<>(operator); + long result = 0; + for (char op : priority.toCharArray()) { + if (!tmpOperator.contains(op)) { + continue; + } + int index; + while ((index = tmpOperator.indexOf(op)) != -1) { + long op1 = tmpNumbers.remove(index + 1); + long op2 = tmpNumbers.get(index); + result = calc(op2, op1, tmpOperator.remove(index)); + tmpNumbers.set(index, result); + } + + } + return result; + } + + private long calc(long op1, long op2, char operator) { + switch (operator) { + case '+': + return op1 + op2; + case '-': + return op1 - op2; + case '*': + return op1 * op2; + } + throw new IllegalArgumentException(); + } +} diff --git a/src/delf/programmers/Solution67258.java b/src/delf/programmers/Solution67258.java new file mode 100644 index 0000000..cf7ed3d --- /dev/null +++ b/src/delf/programmers/Solution67258.java @@ -0,0 +1,39 @@ +package programmers; + +import java.util.*; + +public class Solution67258 { + public int[] solution(String[] gems) { + int[] answer = {1, gems.length}; + Set jewels = new HashSet<>(); + Map counter = new HashMap<>(); + + Collections.addAll(jewels, gems); + + int start = 0, end = 0; + int diff = gems.length; + + while (true) { + if (counter.size() == jewels.size()) { + if (diff > end - start) { + diff = end - start; + answer[0] = start + 1; + answer[1] = end; + } + if (counter.get(gems[start]) == 1) { + counter.remove(gems[start]); + start++; + } else if (counter.get(gems[start]) > 1) { + counter.merge(gems[start], -1, Integer::sum); + start++; + } + } else if (end == gems.length) { + break; + } else { + counter.merge(gems[end], 1, Integer::sum); + end++; + } + } + return answer; + } +} diff --git a/src/delf/programmers/Solution68645.java b/src/delf/programmers/Solution68645.java new file mode 100644 index 0000000..38f9e2f --- /dev/null +++ b/src/delf/programmers/Solution68645.java @@ -0,0 +1,48 @@ +package programmers; + +import java.util.Arrays; + +/** + * 삼각 달팽이 + * https://programmers.co.kr/learn/courses/30/lessons/68645 + */ +public class Solution68645 { + private final static int[][] incremental = {{1, 0}, {0, 1}, {-1, -1}}; // 아래, 오른쪽, 대각선(좌상) + + public int[] solution(int num) { + final int endNumber = num * (1 + num) / 2; + int[][] array = new int[num][num]; + + int n = -1, m = 0; + int direction = 0; + + for (int now = 1; now <= endNumber; ) { // 1 ~ endNumber + for (int i = 0; i < num; i++) { // n ~ 1 + n += incremental[direction][0]; + m += incremental[direction][1]; + array[n][m] = now++; // 방향 번갈아가면서 대입 + } + direction = (direction + 1) % incremental.length; + num--; + } + return convert(array, endNumber); + } + + private int[] convert(int[][] array, int size) { + int[] result = new int[size]; + int cursor = 0; + for (int[] m : array) { + for (int j = 0; j < array[0].length; j++) { + if (m[j] == 0) { + break; + } + result[cursor++] = m[j]; + } + } + return result; + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution68645().solution(6))); + } +} diff --git a/src/delf/programmers/Solution68646.java b/src/delf/programmers/Solution68646.java new file mode 100644 index 0000000..16d302e --- /dev/null +++ b/src/delf/programmers/Solution68646.java @@ -0,0 +1,37 @@ +package programmers; + +/** + * 야근 지수 + * https://programmers.co.kr/learn/courses/30/lessons/68646 + */ +public class Solution68646 { + public int solution(int[] a) { + if (a.length == 1) { + return 1; + } + + int[] leftMin = new int[a.length]; + int[] rightMin = new int[a.length]; + + int tmpMin = Integer.MAX_VALUE; + for (int i = 0; i < a.length; i++) { + tmpMin = Math.min(a[i], tmpMin); + leftMin[i] = tmpMin; + } + + tmpMin = Integer.MAX_VALUE; + for (int i = a.length - 1; i >= 0; i--) { + tmpMin = Math.min(a[i], tmpMin); + rightMin[i] = tmpMin; + } + + int answer = 0; + for (int i = 0; i < a.length; i++) { + if (leftMin[i] < a[i] && rightMin[i] < a[i]) { + continue; + } + answer++; + } + return answer; + } +} diff --git a/src/delf/programmers/Solution68936.java b/src/delf/programmers/Solution68936.java new file mode 100644 index 0000000..292d547 --- /dev/null +++ b/src/delf/programmers/Solution68936.java @@ -0,0 +1,66 @@ +package programmers; + +import java.util.Arrays; + +/** + * 쿼드압축 후 개수 세기 + * https://programmers.co.kr/learn/courses/30/lessons/68936 + */ +public class Solution68936 { + + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution68936().solution(new int[][]{{1, 1, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 1}, {1, 1, 1, 1}}))); + System.out.println(Arrays.toString(new Solution68936().solution(new int[][]{{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}}))); + + } + + public int[] solution(int[][] arr) { + int[] answer = new int[]{0, 0}; + count(arr, arr.length, 0, 0, answer); + return answer; + } + + private int[] count(int[][] arr, int size, int startRow, int startCol, int[] answer) { + int[] count = new int[]{0, 0}; // 이번 범위의 배열에서의 숫자 카운터 + + if (size == 2) { // 최소 단위(2*2)일 때, + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + count[arr[startCol + j][startRow + i]]++; // 각 위치에서 카운팅 + } + } + answer[0] += count[0]; // 결과 배열에 추가 + answer[1] += count[1]; + } else { // 최소 단위가 아닐 때, + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + int nextSize = size / 2; + int nextCol = startCol + (j * nextSize); + int nextRow = startRow + (i * nextSize); + int[] tmp = count(arr, nextSize, nextCol, nextRow, answer); // 배열을 4개로 분할해서 카운팅 + count[0] += tmp[0]; // 4분할한 카운팅 합치기 + count[1] += tmp[1]; + } + } + } + + /* 중복 보정 */ + if (count[1] == 0) { // 배열 내 모든 요소가 '0'이면 ('1'이 없으면) + answer[0] -= 3; // '0'의 카운트 -3 + } + if (count[0] == 0) { // 이하 동문 ('1'인 경우) + answer[1] -= 3; + } + + return count; + } + + private int[] checkCount(int[] answer) { + if (answer[0] == 4) { + answer[0] = 1; + } else if (answer[1] == 4) { + answer[1] = 1; + } + return answer; + } +} diff --git a/src/delf/programmers/Solution70129.java b/src/delf/programmers/Solution70129.java new file mode 100644 index 0000000..541e00f --- /dev/null +++ b/src/delf/programmers/Solution70129.java @@ -0,0 +1,62 @@ +package programmers; + +import java.util.Arrays; + +/** + * 이진 변환 반복하기 + * https://programmers.co.kr/learn/courses/30/lessons/70129 + */ +public class Solution70129 { + public static void main(String[] args) { + System.out.println(Arrays.toString(new Solution70129().solution("110010101001"))); + System.out.println(Arrays.toString(new Solution70129().solution("01110"))); + System.out.println(Arrays.toString(new Solution70129().solution("1111111"))); + } + // 문제의 로직 그대로... + // 1. s에서 0 카운트 + // 2. 그 숫자를 이진수로 변환 + // 3. 그 수가 s + // 4. s가 1이될 때 까지 반복 + public int[] solution(String s) { + + int loopCnt = 0; // 반복 횟수 + int leftOnes; // s에서 남은 1의 개수 + int totalZeroCnt = 0; // 총 0의 개수 + + + do { + // 1. + int zeroCnt = 0; + leftOnes = s.length(); + for (char ch : s.toCharArray()) { + zeroCnt += ((ch == '0') ? 1 : 0); + } + + // 2~3. + leftOnes -= zeroCnt; + totalZeroCnt += zeroCnt; + + s = Integer.toBinaryString(leftOnes); + + loopCnt++; + + } while (leftOnes > 1); // 4. + + /*for (loopCnt = 0; leftOnes > 1; loopCnt++) { + int zeroCnt = 0; + for (char ch : s.toCharArray()) { + if (ch == '0') { + zeroCnt++; + } + } + + leftOnes -= zeroCnt; + totalZeroCnt += zeroCnt; + + s = Integer.toBinaryString(leftOnes); + leftOnes = s.length(); + }*/ + + return new int[]{loopCnt, totalZeroCnt}; + } +} diff --git a/src/delf/programmers/skillcheck/SkillCheck0101.java b/src/delf/programmers/skillcheck/SkillCheck0101.java new file mode 100644 index 0000000..b104cfe --- /dev/null +++ b/src/delf/programmers/skillcheck/SkillCheck0101.java @@ -0,0 +1,25 @@ +package programmers.skillcheck; + +import java.util.*; + +public class SkillCheck0101 { + public static void main(String[] args) { + System.out.println(new SkillCheck0101().solution(new String[]{"marina", "josipa", "nikola", "vinko", "filipa"}, new String[]{"josipa", "filipa", "marina", "nikola"})); + } + + + public String solution(String[] participant, String[] completion) { + Map map = new HashMap<>(); + for (String name : completion) { + map.merge(name, 1, Integer::sum); + } + for (String name : participant) { + Integer n = map.get(name); + if (Objects.isNull(n) || n == 0) { + return name; + } + map.put(name, n - 1); + } + throw new IllegalArgumentException(); + } +} diff --git a/src/delf/programmers/skillcheck/SkillCheck0102.java b/src/delf/programmers/skillcheck/SkillCheck0102.java new file mode 100644 index 0000000..3631133 --- /dev/null +++ b/src/delf/programmers/skillcheck/SkillCheck0102.java @@ -0,0 +1,19 @@ +package programmers.skillcheck; + +public class SkillCheck0102 { + public boolean solution(String s) { + int p = 0; + int y = 0; + for (char ch : s.toCharArray()) { + if (Character.isUpperCase(ch)) { + ch = Character.toLowerCase(ch); + } + if (ch == 'p') { + p++; + } else if (ch == 'y') { + y++; + } + } + return p == y; + } +} diff --git a/src/delf/programmers/skillcheck/SkillCheck0201.java b/src/delf/programmers/skillcheck/SkillCheck0201.java new file mode 100644 index 0000000..38c3f83 --- /dev/null +++ b/src/delf/programmers/skillcheck/SkillCheck0201.java @@ -0,0 +1,27 @@ +package programmers.skillcheck; + +import java.util.Arrays; + +public class SkillCheck0201 { + public static void main(String[] args) { + + } + + public int solution(int[] people, int limit) { + int answer = 0; + + Arrays.sort(people); + int left = 0; + int right = people.length - 1; + + while (left <= right) { + int weight = people[left] + people[right]; + if (weight <= limit) { + left++; + } + right--; + answer++; + } + return answer; + } +} diff --git a/src/delf/programmers/skillcheck/SkillCheck0202.java b/src/delf/programmers/skillcheck/SkillCheck0202.java new file mode 100644 index 0000000..29a82fa --- /dev/null +++ b/src/delf/programmers/skillcheck/SkillCheck0202.java @@ -0,0 +1,29 @@ +package programmers.skillcheck; + +public class SkillCheck0202 { + public static void main(String[] args) { + System.out.println(new SkillCheck0202().solution(new int[]{1, 2, 3, 4})); + System.out.println(new SkillCheck0202().solution(new int[]{1, 2, 7, 6, 4})); + } + + public int solution(int[] nums) { + int cnt = 0; + for (int i = 0; i < nums.length - 2; i++) { + for (int j = i + 1; j < nums.length - 1; j++) { + for (int k = j + 1; k < nums.length; k++) { + cnt += isPrime(nums[i] + nums[j] + nums[k]) ? 1 : 0; + } + } + } + return cnt; + } + + private boolean isPrime(int n) { + for (int i = 2; i * i <= n; i++) { + if (n % i == 0) { + return false; + } + } + return true; + } +} diff --git a/src/delf/programmers/skillcheck/SkillCheck0302.java b/src/delf/programmers/skillcheck/SkillCheck0302.java new file mode 100644 index 0000000..9207ac3 --- /dev/null +++ b/src/delf/programmers/skillcheck/SkillCheck0302.java @@ -0,0 +1,33 @@ +package programmers.skillcheck; + +import java.util.Arrays; + +public class SkillCheck0302 { + public int[] solution(int n, int s) { + int div = s / n; + int rest = s % n; + + if (div == 0) { + return new int[]{-1}; + } + + int[] answer = new int[n]; + Arrays.fill(answer, div); + + if (rest == 0) { + return answer; + } + + int cursor = 0; + for (int i = 0; i < rest; i++, cursor %= n) { + answer[cursor++]++; + } + Arrays.sort(answer); + return answer; + } + + public static void main(String[] args) { + System.out.println(Arrays.toString(new SkillCheck0302().solution(2, 9))); + + } +} diff --git a/src/doy/Solution.java b/src/doy/Solution.java new file mode 100644 index 0000000..fc77ee6 --- /dev/null +++ b/src/doy/Solution.java @@ -0,0 +1,14 @@ +package doy; + +import doy.etc.Doy_Q1000; + +public class Solution { + + public static void main(String[] args) throws Exception { + solution(); + } + + public static void solution() { + Doy_Q1000.run(); + } +} diff --git a/src/doy/leetcode/Two_Sum_1.java b/src/doy/leetcode/Two_Sum_1.java new file mode 100644 index 0000000..2b76b1b --- /dev/null +++ b/src/doy/leetcode/Two_Sum_1.java @@ -0,0 +1,14 @@ +package doy.leetcode; + +public class Two_Sum_1 { + public int[] twoSum(int[] nums, int target) { + for (int i = 0; i < nums.length; i++) { + for (int j = i + 1; j < nums.length; j++) { + if (nums[i] + nums[j] == target) { + return new int[]{i, j}; + } + } + } + return null; + } +} diff --git a/src/hee/Solution.java b/src/hee/Solution.java new file mode 100644 index 0000000..d89c3d7 --- /dev/null +++ b/src/hee/Solution.java @@ -0,0 +1,14 @@ +package hee; + +import hee.boj.etc.Hee_Q1000; + +public class Solution { + + public static void main(String[] args) throws Exception { + solution(); + } + + public static void solution() { + Hee_Q1000.run(); + } +} diff --git a/src/hee/codility/naverfin/Solution1.java b/src/hee/codility/naverfin/Solution1.java new file mode 100644 index 0000000..0aa05fa --- /dev/null +++ b/src/hee/codility/naverfin/Solution1.java @@ -0,0 +1,21 @@ +package hee.codility.naverfin; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public class Solution1 { + public int solution(int[] A) { + Set integers = Arrays.stream(A) + .boxed() + .collect(Collectors.toSet()); + + int result = 0; + for (int value : A) { + if (integers.contains(value + 1)) { + result++; + } + } + return result; + } +} diff --git a/src/hee/codility/naverfin/Solution2.java b/src/hee/codility/naverfin/Solution2.java new file mode 100644 index 0000000..7a2162b --- /dev/null +++ b/src/hee/codility/naverfin/Solution2.java @@ -0,0 +1,32 @@ +package hee.codility.naverfin; + +import java.util.HashSet; +import java.util.Set; + +public class Solution2 { + Set charSet = new HashSet<>(); + + public int solution(String S) { + if (S == null || S.isEmpty()) { + return 0; + } + + int result = 0; + for (int i = 0; i < S.length(); i++) { + String checkChar = Character.toString(S.charAt(i)); + if (charSet.contains(checkChar)) { + result++; + initSet(); + } + charSet.add(checkChar); + } + if (charSet.size() != 0) { + result++; + } + return result; + } + + private void initSet() { + charSet = new HashSet<>(); + } +} diff --git a/src/hee/codility/naverfin/Solution3.java b/src/hee/codility/naverfin/Solution3.java new file mode 100644 index 0000000..4c5d223 --- /dev/null +++ b/src/hee/codility/naverfin/Solution3.java @@ -0,0 +1,15 @@ +package hee.codility.naverfin; + +public class Solution3 { + public boolean solution(int[] A, int K) { + int n = A.length; + for (int i = 0; i < n - 1; i++) { + if (A[i] + 1 < A[i + 1]) + return false; + } + if (A[0] != 1 || A[n - 1] != K) + return false; + else + return true; + } +} diff --git a/src/hee/codility/practice/Practice1.java b/src/hee/codility/practice/Practice1.java new file mode 100644 index 0000000..520c36c --- /dev/null +++ b/src/hee/codility/practice/Practice1.java @@ -0,0 +1,32 @@ +package hee.codility.practice; + +public class Practice1 { + public int solution(int[] A) { + + int[] num1 = new int[]{0, A[0]}; + int[] num2 = new int[]{1, A[1]}; + int length = 2, max = 2; + for (int i = 2; i < A.length; i++) { + int checkNum = A[i]; + if (checkNum == num1[1]) { + num1[0] = i; + length++; + } else if (checkNum == num2[1]) { + num2[0] = i; + length++; + } else { + if (A[i - 1] == num1[1]) { + length = i - num2[0]; + num2[0] = i; + num2[1] = checkNum; + } else { + length = i - num1[0]; + num1[0] = i; + num1[1] = checkNum; + } + } + max = Math.max(max, length); + } + return max; + } +} diff --git a/src/hee/codility/w/Q1_1.java b/src/hee/codility/w/Q1_1.java new file mode 100644 index 0000000..31fb004 --- /dev/null +++ b/src/hee/codility/w/Q1_1.java @@ -0,0 +1,78 @@ +package hee.codility.w; + +import java.util.Stack; + +public class Q1_1 { + public static final int MAX = 0xFFFFF; + public static final int MIN = 0; + private static final Stack stack = new Stack<>(); + + public static void main(String[] args) { +// String string = "13 DUP 4 POP 5 DUP + DUP + -"; + String string = "5 6 + -"; +// String string = "3 DUP 5 - -"; + + String[] strings = string.split(" "); + int result = 0; + for (String s : strings) { + switch (s) { + case "POP": + result = pop(); + break; + case "DUP": + dup(); + break; + case "+": + add(); + break; + case "-": + sub(); + break; + default: + push(Integer.parseInt(s)); + break; + } + } + System.out.println(stack.peek()); +// return stack.peek(); + } + + private static int push(int i) { + if (i < MIN || i > MAX) { + System.out.println(-1); + return -1; +// throw new IllegalArgumentException(""); + } + return stack.push(i); + } + + private static int pop() { + return stack.pop(); + } + + private static void dup() { + hasElements(1); + push(stack.peek()); + } + + private static void add() { + hasElements(2); + push(stack.pop() + stack.pop()); + } + + private static int sub() { + if (hasElements(2) == -1) { + return -1; + } + return push(stack.pop() - stack.pop()); + } + + private static int hasElements(int i) { + if (stack.size() < i) { + System.out.println(-1); + return -1; +// throw new IllegalArgumentException("Too few elements available"); + } + return i; + } +} \ No newline at end of file diff --git a/src/hee/codility/w/Q1_2.java b/src/hee/codility/w/Q1_2.java new file mode 100644 index 0000000..d79d775 --- /dev/null +++ b/src/hee/codility/w/Q1_2.java @@ -0,0 +1,32 @@ +package hee.codility.w; + +import java.util.HashMap; + +public class Q1_2 { + public final static int RADIX = 10; + + public static void main(String[] args) { + String A = "A586QK"; + String B = "JJ653K"; + HashMap hashMap = new HashMap<>(); + + for (int i = 2; i < 10; i++) + hashMap.put(Character.forDigit(i, RADIX), i); + hashMap.put('T', 10); + hashMap.put('J', 11); + hashMap.put('Q', 12); + hashMap.put('K', 13); + hashMap.put('A', 14); + + int cnt = 0; + char[] a = A.toCharArray(); + char[] b = B.toCharArray(); + + for (int i = 0; i < a.length; i++) { + if (hashMap.get(a[i]) > hashMap.get(b[i])) { + cnt++; + } + } + System.out.println(cnt); + } +} diff --git a/src/hee/codility/w/Q1_3.sql b/src/hee/codility/w/Q1_3.sql new file mode 100644 index 0000000..6d38a99 --- /dev/null +++ b/src/hee/codility/w/Q1_3.sql @@ -0,0 +1,20 @@ +with results as( + SELECT host_team as team_id, 3 as points + FROM matches where host_goals > guest_goals + UNION + SELECT guest_team as team_id, 3 as points + FROM matches where host_goals < guest_goals + UNION + SELECT host_team as team_id, 1 as points + FROM matches where host_goals = guest_goals + UNION + SELECT guest_team as team_id, 1 as points + FROM matches where host_goals = guest_goals +), totals as ( + SELECT team_id, SUM(points) as num_points + from results + GROUP BY team_id +) +SELECT t.team_id, t.team_name, COALESCE(totals.num_points, 0) as num_points +FROM teams t LEFT JOIN totals +ON t.team_id = totals.team_id \ No newline at end of file diff --git a/src/hee/codility/w/Q1_4.java b/src/hee/codility/w/Q1_4.java new file mode 100644 index 0000000..797edd0 --- /dev/null +++ b/src/hee/codility/w/Q1_4.java @@ -0,0 +1,23 @@ +package hee.codility.w; + +import java.util.Arrays; + +public class Q1_4 { + public static void main(String[] args) { +// int A = 1, B = 1, C = 2, D = 3; + int A = 2, B = 4, C = 2, D = 4; + + int nums[] = new int[3]; + nums[0] = squaredDistance(A, B, C, D); + nums[1] = squaredDistance(A, C, B, D); + nums[2] = squaredDistance(A, D, B, C); + + Arrays.sort(nums); + System.out.println(nums[2]); +// return nums[2]; + } + + private static int squaredDistance(int n1, int n2, int n3, int n4) { + return (int) Math.pow(n1 - n2, 2) + (int) Math.pow(n3 - n4, 2); + } +} diff --git a/src/hee/codility/w/Q1_5.java b/src/hee/codility/w/Q1_5.java new file mode 100644 index 0000000..f5eb75b --- /dev/null +++ b/src/hee/codility/w/Q1_5.java @@ -0,0 +1,53 @@ +package hee.codility.w; + +import java.util.ArrayList; +import java.util.List; + +public class Q1_5 { + public static void main(String[] args) { + int[] A = {6, 1, 4, 6, 3, 2, 7, 4}; // 2~ + int K = 3, L = 2; + + if (A.length < K + L) { + System.out.println(-1); +// return -1; + } + + // K를 항상 큰 수로 만든다. + if (K < L) { + int tmp = L; + L = K; + K = tmp; + } + + // K개의 연속된 수 중 가장 큰 값을 구한다. + int maxK = Integer.MIN_VALUE; + List indexes = new ArrayList<>(); + for (int i = 0; i <= A.length - K; i++) { + int Ak = 0; + for (int j = i; j < i + K; j++) { + Ak += A[j]; + } + /* 최댓값의 시작 인덱스 저장 */ + if (maxK < Ak) { // 새로운 최댓값 + maxK = Ak; // 최댓값 변경 + indexes.removeAll(indexes); + indexes.add(i); + } else if (maxK == Ak) { // 최댓값과 동일한 값 + indexes.add(i); + } + } + + // 최댓값이 같은 위치에 대해 각각 조사한다. +// for (int i = 0; i < indexes.size(); i++) { +// // K 뽑아낸 위치의 앞쪽 +// if (i >= L) { +// for (int j = 0; j <) +// } +// // K 뽑아낸 위치의 뒷쪽 +// if () { +// +// } +// } + } +} diff --git a/test/hee/codility/SolutionTest.java b/test/hee/codility/SolutionTest.java new file mode 100644 index 0000000..1fd35cf --- /dev/null +++ b/test/hee/codility/SolutionTest.java @@ -0,0 +1,27 @@ +package hee.codility; + +import hee.Solution; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class SolutionTest { + + private Solution solution; + + @Before + public void setUp() { + solution = new Solution(); + } + + @Test + public void test() { +// int[] A = {4, 4, 3, 0, 1, 0}; // 3 +// +// boolean result = solution.solution(A); +// +// assertThat(result, is(true)); + } +} diff --git a/test/hee/codility/naverfin/Solution1Test.java b/test/hee/codility/naverfin/Solution1Test.java new file mode 100644 index 0000000..4efec81 --- /dev/null +++ b/test/hee/codility/naverfin/Solution1Test.java @@ -0,0 +1,34 @@ +package hee.codility.naverfin; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class Solution1Test { + + private Solution1 solution; + + @Before + public void setUp() { + solution = new Solution1(); + } + + @Test + public void test1() { + // test1 +// int[] A = {3, 4, 3, 0, 2, 2, 3, 0, 0}; // 5 +// int[] A = {4, 2, 0}; // 0 + int[] A = {4, 4, 3, 0, 1, 0}; // 3 + +// int[] A = {3, -1, -5, -9}; // 3 +// int[] A = {0, 1}; // 0 +// int[] A = {1, 1, 2, 5, 7}; // 0 +// int[] A = {-1, 1, 3, 3, 3, 2, 3, 2, 1, 0, -1}; // 8 +// int[] A = {-1, -1, -1}; // 1 + int result = solution.solution(A); + + assertThat(result, is(3)); + } +} diff --git a/test/hee/codility/naverfin/Solution2Test.java b/test/hee/codility/naverfin/Solution2Test.java new file mode 100644 index 0000000..886111a --- /dev/null +++ b/test/hee/codility/naverfin/Solution2Test.java @@ -0,0 +1,27 @@ +package hee.codility.naverfin; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class Solution2Test { + + private Solution2 solution; + + @Before + public void setUp() { + solution = new Solution2(); + } + + @Test + public void test2() { + // test1 +// String A = "abacdec"; + String A = "dddd"; + int result = solution.solution(A); + + assertThat(result, is(4)); + } +} diff --git a/test/hee/codility/naverfin/Solution3Test.java b/test/hee/codility/naverfin/Solution3Test.java new file mode 100644 index 0000000..8c4229b --- /dev/null +++ b/test/hee/codility/naverfin/Solution3Test.java @@ -0,0 +1,48 @@ +package hee.codility.naverfin; + +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class Solution3Test { + + private Solution3 solution; + + @Before + public void setUp() { + solution = new Solution3(); + } + + @Test + public void test3() { + // test1 +// int[] A = new int[]{1, 1, 2, 4, 5}; +// int K = 5; + +// int[] A = new int[]{1, 1, 3}; +// int K = 2; + +// int[] A = new int[]{1, 1}; +// int K = 1; + +// int[] A = new int[]{1, 1, 2}; +// int K = 1; + + int[] A = new int[]{1, 2, 2, 2, 2, 3}; + int K = 2; + +// int max = 1000000000; +// int[] A = new int[max]; +// for (int i = 0; i < max; i++) { +// A[i] = i + 1; +// } +// int K = 1000000001; + + boolean result = solution.solution(A, K); + +// assertThat(result, is(true)); + assertThat(result, is(false)); + } +}