문제에 이모티콘 표시한 것은 풀 때 조금 어렵거나 새롭게 알게 된 알고리즘이라 다시 풀어보거나 체크해봐야 할 문제이다!
import java.util.*;
class Solution {
public int[] solution(int[] numbers) {
Set<Integer> s = new TreeSet<>();
for(int i = 0; i < numbers.length; i++){
for(int j = i + 1; j < numbers.length; j++){
int sum = numbers[i] + numbers[j];
s.add(sum);
}
}
int[] answer = new int[s.size()];
int idx = 0;
for(int num : s){
answer[idx++] = num;
}
return answer;
}
}| 자료구조 | 내부 구현 | 데이터 순서 (Order) | 평균 시간 복잡도(추가/삭제/검색) | 핵심 요약 |
|---|---|---|---|---|
HashSet | Hash Table | 순서 없음 (뒤죽박죽) | O(1) (가장 빠름) | 단순 중복 제거 끝판왕 |
TreeSet | Red-Black Tree | 오름차순 정렬 (기본값) | O(\log N)(조금 느림) | 중복 제거 + 자동 정렬 마법 |
LinkedHashSet | Hash Table + Linked List | 입력된 순서 유지 | O(1) | 중복 제거 + 들어온 순서 기억 |
| 분류 | 코드 / 메서드 | 설명 |
|---|---|---|
| 기본 사용 방법 | Set<Integer> s = new HashSet<>(); | (가장 기본형인 HashSet 기준) |
| 데이터 추가 | add(item) | 셋에 아이템을 삽입 (중복된 값이면 무시) |
| 데이터 삭제 | remove(item) | 셋에서 특정 아이템을 찾아서 제거 |
| 데이터 확인 | contains(item) | 셋에 해당 아이템이 있는지 반환 (Set의 핵심! 매우 빠름) |
| 비었는지 확인 | isEmpty() | 셋이 비었는지 반환 (true / false) |
| 크기 확인 | size() | 셋에 들어있는 고유한 원소의 개수 반환 |
| 초기화 | clear() | 셋의 모든 원소를 한 번에 싹 제거 |
import java.util.*;
class Solution {
public int solution(String s) {
int answer = 0;
StringBuilder sb = new StringBuilder();
StringBuilder tmp = new StringBuilder();
Map<String, Integer> m = new HashMap<>();
m.put("zero", 0);
m.put("one", 1);
m.put("two", 2);
m.put("three", 3);
m.put("four", 4);
m.put("five", 5);
m.put("six", 6);
m.put("seven", 7);
m.put("eight", 8);
m.put("nine", 9);
for(char ch : s.toCharArray()){
if(Character.isDigit(ch)){
if(tmp.length() > 0){
sb.append(m.get(tmp.toString()));
tmp.setLength(0);
}
sb.append(ch);
}
else{
tmp.append(ch);
if(m.containsKey(tmp.toString())){
sb.append(m.get(tmp.toString()));
tmp.setLength(0);
}
}
}
return Integer.parseInt(sb.toString());
}
}
// 개선
class Solution {
public int solution(String s) {
String[] words = {"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine"};
for(int i = 0; i < 10; i++){
s = s.replace(words[i], Integer.toString(i));
}
return Integer.parseInt(s);
}
}| 자료구조 | 데이터 순서 (Key 기준) | 언제 쓸까? (실무 선택 가이드) |
|---|---|---|
HashMap | 순서 없음 (뒤죽박죽) | "순서 상관없이 Key로 Value만 엄청 빨리 찾고 싶어!" (99% 확률로 이거 씀) |
TreeMap | 오름차순 정렬 (Key 기준) | "Key 값을 기준으로 가나다순, 123순 예쁘게 정렬해서 저장해야 해!" |
LinkedHashMap | 입력된 순서 유지 | "내가 put으로 데이터를 집어넣은 순서표를 그대로 기억해 줬으면 좋겠어!" |
| 분류 | 코드 / 메서드 | 설명 |
|---|---|---|
| 기본 사용 방법 | Map<String, Integer> m = new HashMap<>(); | (가장 기본형인 HashMap 기준) |
| 데이터 추가/수정 | put(key, value) | 맵에 Key-Value 쌍을 삽입 (이미 있는 Key면 Value가 덮어씌워짐!) |
| 데이터 꺼내기 | get(key) | Key를 주고, 그에 맞는 Value를 반환 (없으면 null 반환) |
| 데이터 꺼내기 | getOrDefault(key, 기본값) | Key를 주고, 그에 맞는 Value를 반환(없으면 기본값 반환) |
| 데이터 삭제 | remove(key) | 맵에서 해당 Key와 그에 딸린 Value를 통째로 제거 |
| Key 존재 확인 | containsKey(key) | 맵에 해당 Key가 있는지 반환 (true / false) |
| Value 존재 확인 | containsValue(value) | 맵에 해당 Value가 있는지 반환 (Key 탐색보단 느림) |
| 비었는지 확인 | isEmpty() | 맵이 비었는지 반환 (true / false) |
| 크기 확인 | size() | 맵에 들어있는 Key-Value 쌍의 개수 반환 |
| Key만 다 뽑기 | keySet() | 맵에 있는 모든 Key만 모아서 Set 형태로 반환 (for문 돌릴 때 필수!) |
import java.util.*;
class Solution {
public int[] solution(int[] array, int[][] commands) {
int[] answer = new int[commands.length];
for(int i = 0; i < commands.length; i++){
int from = commands[i][0], to = commands[i][1], target = commands[i][2];
int[] tmp = Arrays.copyOfRange(array, from - 1, to);
Arrays.sort(tmp);
answer[i] = tmp[target - 1];
}
return answer;
}
}class Solution {
public int solution(int a, int b, int n) {
int answer = 0;
while(n >= a){
answer += n / a * b;
n = (n / a) * b + (n % a);
}
return answer;
}
}import java.util.*;
class Solution {
public int[] solution(int k, int[] score) {
int[] answer = new int[score.length];
for(int i = 0; i < score.length; i++){
int[] tmp = Arrays.copyOfRange(score, 0, i + 1);
Arrays.sort(tmp);
if(tmp.length < k) answer[i] = tmp[0];
else answer[i] = tmp[tmp.length - k];
}
return answer;
}
}
// 개선(우선순위 큐)
import java.util.*;
class Solution {
public int[] solution(int k, int[] score) {
int[] answer = new int[score.length];
PriorityQueue<Integer> pq = new PriorityQueue<>();
for(int i = 0; i < score.length; i++) {
pq.add(score[i]);
if (pq.size() > k) {
pq.poll();
}
answer[i] = pq.peek();
}
return answer;
}
}| 자료구조 | 데이터 입출력 방식 |
|---|---|
Queue(LinkedList) | FIFO (First In First Out) 먼저 들어간 놈이 먼저 나옵니다. |
PriorityQueue | 우선순위 (최솟값/최댓값) 순서 상관없이 지정된 기준(VIP)이 먼저 나옵니다. |
Deque(ArrayDeque) | 양방향 입출력 (만능) 앞으로도 넣고 빼고, 뒤로도 넣고 뺄 수 있습니다. |
| 분류 | 코드 / 메서드 | 설명 (큐 & 데크 공통 및 전용) |
|---|---|---|
| 기본 선언 | Queue<Integer> q = new LinkedList<>();PriorityQueue<Integer> pq = new PriorityQueue<>();Deque<Integer> dq = new ArrayDeque<>(); | 데크는 주로 빠르고 가벼운 ArrayDeque로 만듦 |
| 데이터 넣기 | offer(item) | (공통) 큐의 맨 뒤에 데이터를 집어넣습니다. |
| (데크 전용) | offerFirst(item) / offerLast(item) | [Deque] 맨 앞에 넣기 / 맨 뒤에 넣기 (선택 가능!) |
| 데이터 빼기 | poll() | (공통) 우선순위가 가장 높은(또는 맨 앞) 데이터를 꺼내고 삭제 |
| (데크 전용) | pollFirst() / pollLast() | [Deque] 맨 앞의 데이터 빼기 / 맨 뒤의 데이터 빼기 |
| 데이터 확인 | peek() | (공통) 다음에 나올 데이터가 뭔지 확인만 합니다. (삭제 X) |
| (데크 전용) | peekFirst() / peekLast() | [Deque] 맨 앞 데이터 확인 / 맨 뒤 데이터 확인 |
| 비었는지/크기 | isEmpty() / size() / clear() | (공통) 비었는지 확인 / 데이터 개수 확인 / 싹 다 지우기 |
import java.util.*;
class Solution {
public String[] solution(String[] strings, int n) {
Arrays.sort(strings, (a, b)->{
if(a.charAt(n) == b.charAt(n)) return a.compareTo(b);
return a.charAt(n) - b.charAt(n);
});
return strings;
}
}a - b 가 아니라 a.compareTo(b) 이런 식으로 비교를 해야한다.import java.util.*;
class Solution {
public String solution(String[] cards1, String[] cards2, String[] goal) {
Queue<String> q1 = new LinkedList<>();
Queue<String> q2 = new LinkedList<>();
for(String card : cards1) q1.offer(card);
for(String card : cards2) q2.offer(card);
for(String s : goal){
if(!q1.isEmpty() && q1.peek().equals(s)){
q1.poll();
}
else if(!q2.isEmpty() && q2.peek().equals(s)){
q2.poll();
}
else{
return "No";
}
}
return "Yes";
}
}
// 메모리 절약(투 포인터)
class Solution {
public String solution(String[] cards1, String[] cards2, String[] goal) {
int idx1 = 0, idx2 = 0;
for(String s : goal){
if(idx1 < cards1.length && cards1[idx1].equals(s)){
idx1++;
}
else if(idx2 < cards2.length && cards2[idx2].equals(s)){
idx2++;
}
else{
return "No";
}
}
return "Yes";
}
}import java.util.*;
class Solution {
public int[] solution(String[] name, int[] yearning, String[][] photo) {
int[] answer = new int[photo.length];
Map<String, Integer> m = new HashMap<>();
for(int i = 0; i < name.length; i++){
m.put(name[i], yearning[i]);
}
int idx = 0;
for(String[] p : photo){
int y = 0;
for(String n : p){
y += m.getOrDefault(n, 0);
}
answer[idx++] = y;
}
return answer;
}
}get이 아닌 getOrDefault 를 활용하여 해결import java.util.*;
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
for(int i = 0; i < n; i++){
char[] c1 = change(arr1[i], n);
char[] c2 = change(arr2[i], n);
char[] ch = new char[n];
for(int j = 0; j < n; j++){
ch[j] = (c1[j] == '1' || c2[j] == '1')? '#' : ' ';
}
answer[i] = String.valueOf(ch);
}
return answer;
}
private char[] change(int num, int n){
StringBuilder sb = new StringBuilder();
while(num != 0){
sb.append((char)(num % 2 + '0'));
num /= 2;
}
while(sb.length() != n){
sb.append('0');
}
return sb.reverse().toString().toCharArray();
}
}
// 비트 연산자 풀이
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
for (int i = 0; i < n; i++) {
int combined = arr1[i] | arr2[i];
String mapRow = Integer.toBinaryString(combined).replace('1', '#').replace('0', ' ');
while (mapRow.length() < n) {
mapRow = " " + mapRow;
}
answer[i] = mapRow;
}
return answer;
}
}비트 연산
| 연산자 | 이름 | 동작 규칙 (비유) |
|---|---|---|
| `A | B` | OR (논리 합) |
A & B | AND (논리 곱) | 둘 모두 1이면 1 |
A ^ B | XOR (배타적 논리 합) | 서로 다르면 1 같으면 0 |
~A | NOT (논리 부정) | 0은 1로 1은 0으로 |
import java.util.*;
class Solution {
public int solution(int[] nums) {
Set<Integer> s = new HashSet<>();
for(int num : nums) s.add(num);
if(s.size() >= nums.length / 2) return nums.length / 2;
return s.size();
}
}class Solution {
public int solution(int number, int limit, int power) {
int answer = 0;
for(int i = 1; i <= number; i++){
int c = cnt(i, limit, power);
answer += c;
}
return answer;
}
private int cnt(int num, int limit, int power){
int cnt = 0;
for(int i = 1; i * i <= num; i++){
if(i * i == num) cnt++;
else if(num % i == 0) cnt += 2;
if(cnt > limit){
cnt = power;
break;
}
}
return cnt;
}
}import java.util.*;
class Solution {
public int[] solution(int[] answers) {
int[] person1 = {1, 2, 3, 4, 5};
int[] person2 = {2, 1, 2, 3, 2, 4, 2, 5};
int[] person3 = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int p1 = 0, p2 = 0, p3 = 0;
for(int i = 0; i < answers.length; i++){
if(answers[i] == person1[i % 5]) p1++;
if(answers[i] == person2[i % 8]) p2++;
if(answers[i] == person3[i % 10]) p3++;
}
int max = Math.max(p1, Math.max(p2, p3));
ArrayList<Integer> list = new ArrayList<>();
if(max == p1) list.add(1);
if(max == p2) list.add(2);
if(max == p3) list.add(3);
return list.stream().mapToInt(i ->i).toArray();
}
}class Solution {
public String solution(int a, int b) {
int[] month = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30};
int day = 0;
for(int i = 0; i < a - 1; i++) day += month[i];
day += b - 1;
String[] days = {"FRI", "SAT", "SUN", "MON", "TUE", "WED", "THU"};
return days[day % 7];
}
}class Solution {
public int solution(int n, int m, int[] section) {
int answer = 0;
int e = 0;
for(int i = 0; i < section.length; i++){
e = section[i] + m - 1;
for(int j = i + 1; j < section.length; j++){
if(section[j] > e) break;
i++;
}
answer++;
}
return answer;
}
}
// 개선
class Solution {
public int solution(int n, int m, int[] section) {
int answer = 0;
int painted = 0;
for (int s : section) {
if (s > painted) {
answer++;
painted = s + m - 1;
}
}
return answer;
}
}import java.util.*;
class Solution {
public int solution(int k, int m, int[] score) {
int answer = 0;
Arrays.sort(score);
int min = 10, select = 0;
for(int i = score.length - 1; i >= 0; i--){
if(select == m){
answer += min * m;
select = 0;
}
min = Math.min(min, score[i]);
select++;
}
if(select == m){
answer += min * m;
}
return answer;
}
}
// 개선
import java.util.*;
class Solution {
public int solution(int k, int m, int[] score) {
int answer = 0;
Arrays.sort(score);
for(int i = score.length - m; i >= 0; i -= m) {
answer += score[i] * m;
}
return answer;
}
}class Solution {
public int solution(int[] wallet, int[] bill) {
int answer = 0;
int max_w = Math.max(wallet[0], wallet[1]);
int min_w = Math.min(wallet[0], wallet[1]);
int max_b = Math.max(bill[0], bill[1]);
int min_b = Math.min(bill[0], bill[1]);
while(true){
if(min_w < min_b || max_w < max_b){
max_b /= 2;
answer++;
}
if(max_b < min_b){
int tmp = min_b;
min_b = max_b;
max_b = tmp;
}
if(max_w >= max_b && min_w >= min_b) break;
}
return answer;
}
}class Solution {
public int solution(int[] nums) {
int answer = 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++){
if(isPrime(nums[i] + nums[j] + nums[k])) answer++;
}
}
}
return answer;
}
boolean isPrime(int num){
for(int i = 2; i <= (int)Math.sqrt(num); i++){
if(num % i == 0){
return false;
}
}
return true;
}
}class Solution {
public int solution(int n) {
int answer = 0;
for(int i = 1; i <= n; i++){
if(isPrime(i)) answer++;
}
return answer;
}
private boolean isPrime(int num){
if(num < 2) return false;
for(int i = 2; i <= (int)Math.sqrt(num); i++){
if(num % i == 0) return false;
}
return true;
}
}
// 개선
import java.util.*;
class Solution {
public int solution(int n) {
int answer = 0;
boolean[] isPrime = new boolean[n + 1];
Arrays.fill(isPrime, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= (int)Math.sqrt(n); i++) {
if (isPrime[i]) {
for (int j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}
for (int i = 2; i <= n; i++) {
if (isPrime[i]) answer++;
}
return answer;
}
}class Solution {
public int solution(String[] babbling) {
String[] str = {"aya", "ye", "woo", "ma"};
int answer = 0;
for(String st : babbling){
for(String s : str){
st = st.replaceFirst(s, " ");
}
st = st.replace(" ", "");
if(st.equals("")) answer++;
}
return answer;
}
}
// 해결
class Solution {
public int solution(String[] babbling) {
String[] str = {"aya", "ye", "woo", "ma"};
int answer = 0;
for(String st : babbling){
if(st.contains("ayaaya") || st.contains("yeye") || st.contains("woowoo") || st.contains("mama")) {
continue;
}
for(String s : str){
st = st.replace(s, " ");
}
st = st.replace(" ", "");
if(st.equals("")) answer++;
}
return answer;
}
}import java.util.*;
class Solution {
public int[] solution(int N, int[] stages) {
Arrays.sort(stages);
int[] num = new int[N + 1];
int[] fail = new int[N + 1];
for(int i = 0; i < stages.length; i++){
int s = stages[i];
if(s > N) continue;
if(num[s] == 0) num[s] = stages.length - i;
fail[s]++;
}
Map<Integer, Double> m = new HashMap<>();
for(int i = 1; i <= N; i++){
double percent = 0.0;
if(num[i] == 0) percent = 0.0;
else percent = (double)fail[i] / num[i];
m.put(i, percent);
}
List<Integer> list = new ArrayList<>(m.keySet());
list.sort((a, b)->Double.compare(m.get(b), m.get(a)));
return list.stream().mapToInt(i->i).toArray();
}
}