Developer : 태하팍/코딩 테스트

코테대비 문법정리

태하팍 2025. 9. 18. 11:40
반응형

HashMap

생성

// HashMap 만들기
Map<String, Integer> map = new HashMap<>();

값 추가

map.put("apple", 3);   // apple → 3 저장
map.put("banana", 5);  // banana → 5 저장
map.put("apple", 10);  // apple → 10 (덮어쓰기)

값 읽기

int v = map.get("apple");    // 10
Integer x = map.getOrDefault("orange", 0); // 없으면 기본값 0
boolean hasKey = map.containsKey("apple"); // true/false

값 삭제

map.remove("apple");
map.clear(); // 모든 키·값 삭제

반복

// 1) 키 기준
for (String key : map.keySet()) {
    System.out.println(key + " = " + map.get(key));
}

// 2) 키·값 쌍
for (Map.Entry<String, Integer> e : map.entrySet()) {
    System.out.println(e.getKey() + " = " + e.getValue());
}

코딩테스트에서 자주 사용되는 조합

문자빈도 : 문자열을 char단위로 돌면서 세기

Map<Character,Integer> freq = new HashMap<>();
for (char c : s.toCharArray()) {
    freq.put(c, freq.getOrDefault(c, 0) + 1);
}

배열값 카운트

for (int x : arr) {
    map.put(x, map.getOrDefault(x, 0) + 1);
}

최대 최소값 구하기
Collections.max & Collections.min
Map에서 값 중 가장 큰 값 or 가장 작은 값을 쉽게 가져옴

Map<String,Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 5);
map.put("orange", 2);

// 최대값
int max = Collections.max(map.values());   // 5
// 최소값
int min = Collections.min(map.values());   // 2

/*
   map.values()   // => [3, 5, 2]  (순서는 HashMap 특성상 랜덤)
*/

값이 가장 큰 key구하기
값이 가장 큰 걸 구하고 다시 순회하면서 키를 구함.
예) 최다 득표 후보, 가장 많이 팔린 상품 찾기 등.

int max = Collections.max(map.values());
String maxKey = null;

for (Map.Entry<String,Integer> e : map.entrySet()) {
    if (e.getValue() == max) {
        maxKey = e.getKey();
        break; // 여러 개면 첫 번째만
    }
}

System.out.println(maxKey); // "banana"

정렬
HashMap은 순서가 없음.
키순으로 정렬하려면 TreeMap을 사용!
디폴트가 오름차순

Map<String,Integer> sorted = new TreeMap<>(map);

System.out.println(sorted);
// {apple=3, banana=5, orange=2}  ← 알파벳 순

내림차순으로 하려면

Map<String,Integer> sortedDesc = new TreeMap<>(Collections.reverseOrder());
sortedDesc.putAll(map); // 키 내림차순

ArrayList

선언

// 타입 지정
ArrayList<Integer> list = new ArrayList<>();

// 초기 용량 지정 (선택)
ArrayList<Integer> list = new ArrayList<>(100);

// 값 추가
list.add(10);
list.add(20);

반복문

// 1. 인덱스로
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// 2. 향상된 for
for (int num : list) {
    System.out.println(num);
}

// 3. forEach (Java8+)
list.forEach(System.out::println);

정렬

// 오름차순
Collections.sort(list);

// 내림차순
Collections.sort(list, Collections.reverseOrder());

// 사용자 정의 정렬
list.sort((a, b) -> a - b);       // 오름차순
list.sort((a, b) -> b - a);       // 내림차순

변환

// 배열 → ArrayList
int[] arr = {1, 2, 3};
ArrayList<Integer> list = new ArrayList<>();
for (int x : arr) list.add(x);

// ArrayList → 배열
Integer[] arr2 = list.toArray(new Integer[0]);

toArray(new Integer[0] <--- 타입 참고하기 위해 파라미터로 넣음.
아래와 같이 다른 타입들도 가능(Wrapper Class사용, int,double같은 기본타입 X)

값조회 및 수정

// get : 인덱스 값 가져오기
int first = list.get(0); // 10

// set : 특정 인덱스 값 수정
list.set(2, 25);
System.out.println(list); // [10, 15, 25, 30]

// size : 리스트 길이
System.out.println("크기: " + list.size()); // 4

값 삭제

// remove(index) : 인덱스로 삭제
list.remove(1);
System.out.println(list); // [10, 25, 30]

// remove(Object) : 값으로 삭제 (첫 번째만 삭제)
list.remove(Integer.valueOf(25)); remove가 int와 Object가 있음 주의! 여기선 Object!
System.out.println(list); // [10, 30]

// clear : 전체 삭제
list.clear();
System.out.println(list); // []

contains & indexOf

import java.util.*;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(20);
        list.add(30);
        list.add(20);

        // contains : 값이 리스트에 존재하는지 true/false
        System.out.println(list.contains(20)); // true
        System.out.println(list.contains(99)); // false

        // indexOf : 값이 처음 등장하는 인덱스 (없으면 -1)
        System.out.println(list.indexOf(20)); // 1  (첫 20의 위치)
        System.out.println(list.indexOf(99)); // -1 (없음)
    }
}

 

HashSet

용도 : 중복제거
주요메소드

set.add(x);
set.remove(x);
set.contains(x);
set.size();

간단 예제

Set<Integer> set = new HashSet<>();
set.add(1);
set.add(1);
System.out.println(set.size()); // 1 (중복 제거됨)
System.out.println(set.contains(1)); // true

 

Queue(일반적으로 LinkedList 사용)

용도 : FIFO(First In First Out) 

주요메소드

queue.offer(x);   // 넣기
queue.poll();     // 꺼내기 (없으면 null), 큐에서 꺼냄
queue.peek();     // First Out할 데이터 확인 (없으면 null), 그냥 확인만
  • 패턴 예시
    • BFS(너비 우선 탐색)
    • → 예: “미로 최단 거리” 문제
    • 시뮬레이션
    • → 예: “프린터 대기열, 프로세스 처리 순서”
Queue<Integer> q = new LinkedList<>();
q.offer(1);
q.offer(2);
System.out.println(q.poll()); // 1
System.out.println(q.peek()); // 2

Queue나 Deque으로 쓸 수 있으나, 빈번한 삽입/삭제가 많을 때만 장점이 있음.
보통 큐로 쓰일 때 ArrayDeque가 더 빠르지만, 양방향 연결 리스트 특성으로 중간 삽입/삭제가 잦으면 여전히 사용.

import java.util.LinkedList;
import java.util.Queue;
import java.util.Deque;

// 큐처럼 사용
Queue<String> q = new LinkedList<>();
q.offer("A");
q.offer("B");
System.out.println(q.poll()); // "A"

// 덱처럼 사용
Deque<String> dq = new LinkedList<>();
dq.offerFirst("X");
dq.offerLast("Y");
System.out.println(dq.pollFirst()); // "X"

 

Deque (ArrayDeque 권장)

용도 : 양쪽 끝에서 삽입/삭제가 모두 O(1)

  • ArrayDequeLinkedList보다 메모리와 속도 모두 유리해 코테에서 권장

주요메소드

dq.offerFirst(x); 
dq.offerLast(x);

dq.pollFirst();   
dq.pollLast();

dq.peekFirst();   
dq.peekLast();
  • 패턴 예시
    • 슬라이딩 윈도우 최대/최소
    • → 예: “윈도우 내 최대값 유지”
    • 양쪽에서 꺼내야 하는 문제
    • → 예: “회전하는 큐”, “덱 시뮬레이션”
Deque<Integer> dq = new ArrayDeque<>();
dq.offerFirst(1);
dq.offerLast(2);
System.out.println(dq.pollFirst()); // 1
System.out.println(dq.pollLast());  // 2

양쪽에서 넣고 빼기 모두 O(1) → Queue나 Deque으로 많이 사용
LinkedList보다 속도·메모리 효율이 좋음.

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue; // 큐처럼 쓰려면

// 큐로 사용
Queue<Integer> q = new ArrayDeque<>();
q.offer(10);
q.offer(20);
System.out.println(q.poll()); // 10

// 덱(Deque)으로 사용
Deque<Integer> dq = new ArrayDeque<>();
dq.offerFirst(1);   // 앞에 넣기
dq.offerLast(2);    // 뒤에 넣기
System.out.println(dq.pollLast()); // 2

 

Stack (ArrayDeque 권장)

용도 : LIFO(Last In First Out) - 마지막에 넣은 것이 먼저 나감

  • 옛날엔 java.util.Stack 클래스를 썼지만
  • → 요즘은 ArrayDeque로 Stack 역할을 구현하는 게 빠르고 권장됨.

주요메소드

stack.push(x); // 넣기
stack.pop();   // 꺼내기
stack.peek();  // 확인
  • 패턴 예시
    • 괄호 짝 맞추기
    • → 예: “{[()]} 올바른 괄호 문자열인지 판별”
    • DFS (깊이 우선 탐색)
    • 문자열 뒤집기
Deque<Integer> stack = new ArrayDeque<>();
stack.push(10);
stack.push(20);
System.out.println(stack.pop()); // 20
System.out.println(stack.peek()); // 10

 

PriorityQueue(우선순위 큐)

용도 : 우선순위가 높은 것부터 꺼낼 때 (기본은 최소 힙)

주요메소드

pq.offer(x); // 넣기
pq.poll();   // 가장 작은 값 꺼내기
pq.peek();   // 가장 작은 값 확인
  • 내림차순(최대 힙)으로 쓰고 싶을 때
PriorityQueue<Integer> maxPQ =
    new PriorityQueue<>(Collections.reverseOrder());
  • 패턴 예시
    • K번째 큰/작은 수 찾기
    • 힙(Heap) 기반 문제
    • → 예: “가장 짧은 작업 먼저 처리(SJF 스케줄링)”
    • “다익스트라 최단 경로”, “네트워크 지연 시간”
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5);
pq.offer(1);
pq.offer(3);
System.out.println(pq.poll()); // 1 (가장 작은 값부터)

기본적으로 작은 값이 먼저 나오는 최소 힙 구조
큰 값이 먼저 나오게 하려면 Collections.reverseOrder()와 함께 사용.

import java.util.PriorityQueue;
import java.util.Collections; // (내림차순이 필요할 때만)

PriorityQueue<Integer> pq = new PriorityQueue<>();                // 기본: 오름차순(최소 힙)
PriorityQueue<Integer> maxPq = new PriorityQueue<>(Collections.reverseOrder()); // 내림차순(최대 힙)

// 사용 예
pq.offer(5);
pq.offer(1);
pq.offer(3);
System.out.println(pq.poll()); // 1 (가장 작은 값부터 꺼냄)

 


  • HashSet: 중복 제거·빠른 검색
  • Queue/Deque: BFS, 양쪽 처리, 슬라이딩 윈도우
  • Stack: 괄호·DFS
  • PriorityQueue: K번째 값, 최소·최대값 즉시 꺼내기

문자열 관련

문자열을 문자/배열 변환

String s = "abcde";

// 문자 하나씩 배열로 변환
char[] arr = s.toCharArray(); // ['a','b','c','d','e']

// 특정 위치 문자
char c = s.charAt(2);         // 'c'

// 부분 문자열 (end는 미포함)
String sub = s.substring(1, 4); // "bcd"

문자 ↔ 숫자 변환

char c = '5';

// 문자 숫자를 int로
int n1 = c - '0'; // 5
                  // '5' 아스키코드 값 53, '0'은 48 즉, 53-48 = 5

// 문자열 숫자를 int로
int n2 = Integer.parseInt("123"); // 123

// int → String
String s1 = String.valueOf(123);  // "123"

// char → String
String s2 = String.valueOf(c);    // "5"

* (int)로 캐스팅해서 문자의 아스키코드를 출력할 수 있음.

char c = 'A';
System.out.println((int) c); // 65

문자열 검색과 비교

String s = "Hello World";

int len = s.length();               // 길이
boolean eq = s.equals("Hello World");// 내용 비교 (== 쓰면 안 됨)
boolean st = s.startsWith("He");    // "He"로 시작?
boolean en = s.endsWith("ld");      // "ld"로 끝?
boolean ct = s.contains("lo");      // "lo" 포함?
int pos = s.indexOf('o');           // 'o'의 첫 위치 (없으면 -1)

문자열 수정과 조작

String s = "  a,b,c  ";

s = s.trim();                          // 양쪽 공백 제거 → "a,b,c"
s = s.toUpperCase();                    // 대문자 변환 → "A,B,C"
s = s.toLowerCase();                    // 소문자 변환 → "a,b,c"
s = s.replace('a','z');                 // 문자 교체 → "z,b,c"
s = s.replaceAll("b","bb");             // 정규식 기반 치환 → "z,bb,c"
String[] parts = s.split(",");          // 구분자로 나누기 → ["z","bb","c"]
String joined = String.join("-", parts);// 배열을 합치기 → "z-bb-c"

StringBuilder(성능, 반복 연결에 필수)
String은 immutable이라 +로 여러번 연결하면 느려짐.
반복적으로 문자열을 이어 붙일 때는 StringBuilder 사용을 추천.

StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" World");
sb.insert(5, ",");           // "Hello, World"
sb.deleteCharAt(5);          // "Hello World"
sb.reverse();                // "dlroW olleH"
String result = sb.toString();

자주 사용되는 패턴

// 문자 빈도 세기
String s = "apple";
int[] freq = new int[26];
for (char c : s.toCharArray()) {
    freq[c - 'a']++;
}

/*
freq[c - 'a']++ 동작:
	•	'a' - 'a' → 0 → freq[0]++
	•	'p' - 'a' → 15 → freq[15]++
	•	'p' - 'a' → 15 → freq[15]++
	•	'l' - 'a' → 11 → freq[11]++
	•	'e' - 'a' → 4  → freq[4]++

결과:
freq[0] = 1, freq[4] = 1, freq[11] = 1, freq[15] = 2
나머지는 전부 0.

*/

// 팰린드롬(palindrome) 검사 (양쪽 비교)
String s = "level";
int l = 0, r = s.length() - 1;
boolean isPal = true;
while (l < r) {
    if (s.charAt(l++) != s.charAt(r--)) {
        isPal = false;
        break;
    }
}
/*
코딩테스트에서 자주 나오는 패턴
• 문자열이 회문(palindrome)인지 검사하기
• 숫자를 문자열로 바꾼 뒤 회문인지 판별하기 (예: 121 → true)
• 가장 긴 회문 부분 문자열 찾기(고급 문제)
*/


// 아나그램 검사 (정렬 후 비교)
// 아나그램(Anagram)은 문자 순서는 다르지만 구성된 문자가 같은 문자열을 말합니다.
// 예: "listen" ↔ "silent", "race" ↔ "care".
// 팁 : 길이가 다르면 아나그램일수 없음, 미리 길이부터 체크!
import java.util.*;

public class Main {
    public static void main(String[] args) {
        String s1 = "listen";
        String s2 = "silent";

        // 1) 문자열을 문자 배열로 변환
        char[] c1 = s1.toCharArray();
        char[] c2 = s2.toCharArray();

        // 2) 각 배열을 알파벳 순으로 정렬
        Arrays.sort(c1);
        Arrays.sort(c2);

        // 3) 정렬된 배열이 같으면 아나그램
        boolean isAnagram = Arrays.equals(c1, c2); 
        // 두 배열의 원소가 순서까지 완전히 같으면 true를 반환합니다.

        System.out.println(isAnagram); // true
    }
}

 

정수 나눗셈 올림(ceil)

(양의 정수 a, b에 대해)
ceil(a / b) = (a + b - 1) / b

ceil(a / b) = (a / b) + (a % b > 0 ? 1 : 0)을 한 줄로 만들면 ceil(a / b) = (a + b - 1) / b

왜 +b-1?

  • ab로 나누면 몫 q, 나머지 r (0 ≤ r < b)
  • a = q*b + r
  • a + (b - 1) = q*b + r + (b - 1)

여기서

  • r = 0 (나눠떨어짐) → q*b + (b - 1)를 b로 나누면 몫은 q
  • r > 0 (조금 남음) → q*b + (b - 1 + r)에서 (b - 1 + r) ≥ b → 몫이 q+1
  • => 그래서 자동으로 올림 효과가 나는 것.

 

배열 -> 리스트

Arrays.asList()
배열을 고정 크기의 리스트로

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);
// list = [a, b, c]
  • 고정 크기라 add/remove 불가 (수정하려면 new ArrayList<>(...) 로 감싸기)
List<String> modifiable = new ArrayList<>(Arrays.asList(arr));

문자 배열 → 문자열

char[] chars = {'h','e','l','l','o'};
String s = new String(chars);

 

리스트 → 배열
toArray()

List<Integer> list = Arrays.asList(1, 2, 3);
Integer[] arr = list.toArray(new Integer[0]);
// arr = {1, 2, 3}
  • new Integer[0] 는 타입과 크기만 알려주는 용도
  • (크기를 0으로 줘도 list.size()만큼 자동으로 새 배열을 만들어줌)
List<String> list = Arrays.asList("a", "b");
String[] arr = list.toArray(new String[0]);

 

문자열 뒤집기(역순)

1) StringBuilder 활용 (가장 간단)

String s = "abcdef";
String reversed = new StringBuilder(s).reverse().toString();
// reversed = "fedcba"

2) 배열로 직접 뒤집기

String s = "abcdef";
char[] arr = s.toCharArray();
for (int l = 0, r = arr.length - 1; l < r; l++, r--) {
    char tmp = arr[l];
    arr[l] = arr[r];
    arr[r] = tmp;
}
String reversed = new String(arr);

 

배열복사

Arrays.copyOf
새 배열을 만들고 길이 지정 가능

int[] arr = {1, 2, 3, 4};
int[] copy = Arrays.copyOf(arr, arr.length); // [1, 2, 3, 4]
int[] firstTwo = Arrays.copyOf(arr, 2);      // [1, 2]

clone()
원본과 동일한 길이의 완전 복제

int[] arr = {1, 2, 3};
int[] copy = arr.clone();
copy[0] = 99;
System.out.println(Arrays.toString(arr));  // [1, 2, 3]  (원본 안 바뀜)

리스트로 변환 후 복사 (가변 크기)
배열을 리스트로 변환해 추가·삭제 가능하게 사용

String[] arr = {"a", "b", "c"};
List<String> list = new ArrayList<>(Arrays.asList(arr));
list.add("d");  // 가능
list.remove("a");

Shallow Copy(얕은복사)

int[] arr1 = {1, 2, 3};
int[] arr2 = {4, 5, 6};

// arr1이 arr2를 가리키도록 변경
arr1 = arr2;

arr1[0] = 99;
System.out.println(Arrays.toString(arr1)); // [99, 5, 6]
System.out.println(Arrays.toString(arr2)); // [99, 5, 6] ← 같이 바뀜!

Deep Copy(깊은복사)

int[] arr1 = {1, 2, 3};
int[] arr2 = Arrays.copyOf(arr1, arr1.length);

arr2[0] = 99;
System.out.println(Arrays.toString(arr1)); // [1, 2, 3] ← 그대로
System.out.println(Arrays.toString(arr2)); // [99, 2, 3]

 

반응형