코테


1. [Java] 암호 해독 - cipher.charAt(i - 1)


https://school.programmers.co.kr/learn/courses/30/lessons/120892

오답

class Solution {
    public String solution(String cipher, int code) {
        StringBuilder sb = new StringBuilder();
        for (int i = code; i <= cipher.length(); code++;) {
            sb.append(cipher[i-1]); // 인덱스는 0부터 시작
        }
        return sb.toString();
    }
}


✅ for문의 증가식 오류
for (int i = code; i <= cipher.length(); code++;)


✅ 문자열 인덱스 접근 오류


정답 코드

class Solution {
    public String solution(String cipher, int code) {
        StringBuilder sb = new StringBuilder();
        for (int i = code; i <= cipher.length(); i += code) {
            sb.append(cipher.charAt(i - 1)); // 인덱스는 0부터 시작
        }
        return sb.toString();
    }
}



2. [Java] 대문자와 소문자

https://school.programmers.co.kr/learn/courses/30/lessons/120893

오답

class Solution {
    public String solution(String my_string) {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < my_string.length(); i++) {
            if(Character.isUpperCase((my_string.charAt(i)))) {
                sb.append(Character.toLowerCase(my_string.charAt(i)));
            } else {
                sb.append(Character.toUpperCase(my_string.charAt(i)));
            }
        }
        return sb.toString();
    }
}

✅ my_string.charAt(i)는 위로 빼서 char c = my_string.charAt(i); 로 만들어 주면 코드가 간단해진다.


개선한 코드

class Solution {
    public String solution(String my_string) {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < my_string.length(); i++) {
            char c = my_string.charAt(i);
            if(Character.isUpperCase(c)) {
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(Character.toUpperCase(c));
            }
        }
        return sb.toString();
    }
}



3. [Java] 영어가 싫어요 - numbers.replaceAll(a,b);

https://school.programmers.co.kr/learn/courses/30/lessons/120894

오답

class Solution {
    public long solution(String numbers) {
        String[] words = {
            "zero", "one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine"
        };
        for (int i = 0; i < words.length; i++) {
            numbers = numbers.replace(words[i], String.valueOf(i));
        }
        return Integer.parseInt(numbers);
    }
}

테스트는 통과했으나 답안 제출시 런타임 에러

image.png

image.png

✅ Integer.parseInt() 사용 시 런타임 에러

개선한 코드

class Solution {
    public long solution(String numbers) {
        String[] words = {
            "zero", "one", "two", "three", "four", "five",
            "six", "seven", "eight", "nine"
        };
        for (int i = 0; i < words.length; i++) {
            numbers = numbers.replaceAll(words[i], String.valueOf(i));
        }
        return Long.parseLong(numbers); // ✅ int → long 으로 변경
    }
}



기본형 VS 래퍼클래스


✅ 기본형 (Primitive type)
👉 메모리에 값 자체를 저장함
👉 성능이 빠르고 메모리 사용이 효율적


✅ 참조형 (Reference type, Wrapper class)
👉 객체이기 때문에 null 값을 가질 수 있음
👉 ArrayList<Integer>처럼 제네릭에 사용 가능
👉 기본형은 제네릭에서 사용할 수 없음 → 참조형 필요



4. [Java] 인덱스 바꾸기 - return new String(arr);

https://school.programmers.co.kr/learn/courses/30/lessons/120895

오답

class Solution {
    public String solution(String my_string, int num1, int num2) {
        String[] arr = String.toCharArray(my_string);
        char tmp = arr[num1];
        arr[num1] = arr[num2];
        arr[num2] = tmp;
        return arr.toString();
    }
}
✅ String[] arr = String.toCharArray(my_string);
✅ String.toCharArray() 용법
✅ return arr.toString();


개선한 코드

class Solution {
    public String solution(String my_string, int num1, int num2) {
        char[] arr = my_string.toCharArray();
        char tmp = arr[num1];
        arr[num1] = arr[num2];
        arr[num2] = tmp;
        return new String(arr);
    }
}



클래스 메서드 VS 인스턴스 메서드


자바에서 메서드는 크게 인스턴스 메서드와 **클래스 메서드(static 메서드)**로 나뉘는데, 이 둘은 메서드를 어떻게 호출하고 언제 사용하는지에 따라 중요한 차이를 가진다.

클래스 메서드는 static 키워드로 정의되어 있어 객체를 만들지 않아도 클래스 이름으로 바로 호출할 수 있는 메서드이다. 클래스 메서드는 객체의 고유 상태와는 무관하며, 보통 모든 인스턴스에서 공통으로 사용하는 로직을 구현할 때 사용됩니다. 대표적인 예로 Integer.parseInt("123")는 문자열을 정수로 변환하는 클래스 메서드로, Integer라는 클래스 이름만으로 바로 호출할 수 있다.

반면 인스턴스 메서드는 특정 객체가 생성되어야만 사용할 수 있는 메서드이다. 즉, new 키워드로 객체를 만든 후에야 호출이 가능하며, 주로 그 객체의 상태(멤버 변수)를 기반으로 동작한다. 예를 들어, str.length()는 문자열 객체 str의 길이를 반환하는 인스턴스 메서드인데, 이는 str이라는 객체가 존재해야만 호출할 수 있다.

인스턴스 메서드는 객체마다 상태가 다를 수 있기 때문에, 같은 메서드를 호출하더라도 객체에 따라 결과가 달라진다. 예를 들어, Person이라는 클래스에 sayHello()라는 인스턴스 메서드가 있다면, person1.sayHello()와 person2.sayHello()는 각각 다른 이름을 출력한다. 이는 각 인스턴스가 가지고 있는 name 값이 다르기 때문이다.

이처럼 인스턴스 메서드는 객체의 고유한 데이터를 다루고 조작할 때 유용하며, 클래스 메서드는 그와 무관한 공통 기능을 제공할 때 사용된다. 개발자는 기능의 목적에 따라 두 메서드 중 적절한 쪽을 선택해야 한다. 객체마다 달라지는 동작이 필요하다면 인스턴스 메서드, 객체 없이 호출해도 되는 범용적인 기능이라면 클래스 메서드를 사용하는 것이 좋다.


✅ 1. 인스턴스 메서드 (Instance Method)

정의

특징

예시

public class Person {
    String name;

    public void sayHello() {
        System.out.println("Hello, my name is " + name);
    }
}

// 사용
Person p = new Person();
p.name = "Dain";
p.sayHello();  // 출력: Hello, my name is Dain


✅ 2. 클래스 메서드 (Class Method)

정의

특징

예시

public class MathUtil {
    public static int add(int a, int b) {
        return a + b;
    }
}

// 사용
int result = MathUtil.add(3, 5);  // 객체 없이 호출 가능



5. [Java] 한 번만 등장한 문자 (문자열) - sb.toString();

https://school.programmers.co.kr/learn/courses/30/lessons/120896

오답

import java.util.*;

class Solution {
    public String solution(String s) {
        int[] cnt = new int[26];
        
        for(char c : s.toCharArray()) {
            cnt[c - 'a']++;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 26; i++) {
            if (cnt[i] == 1) sb.append((char)i+'a');
        }
        return sb.toString(); 
    }
}

image.png


✅ sb.append((char)i + 'a');
(char)i + 'a' // => 정수 + 정수 → int로 연산됨

→ i + 'a' 전체를 char로 캐스팅해야 문자로 제대로 변환된다.

sb.append((char)(i + 'a'));


개선한 코드

import java.util.*;

class Solution {
    public String solution(String s) {
        int[] cnt = new int[26];
        
        for(char c : s.toCharArray()) {
            cnt[c - 'a']++;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 26; i++) {
            if (cnt[i] == 1) sb.append((char)(i + 'a'));
        }
        return sb.toString(); 
    }
}




16 . [Java] 문자열 여러번 뒤집기 - sb.charAt()

https://school.programmers.co.kr/learn/courses/30/lessons/181913

📌 문제


📌 제한사항


코드

  1. 문자열을 StringBuilder로 변환해서 수정 가능하도록 함
  2. [s, e]에 대해 투포인터로 문자열을 뒤집음
  3. 모든 쿼리를 순서대로 적용 후, 최종 문자열을 반환
import java.util.*;

class Solution {
    public String solution(String s) {
        int[] cnt = new int[26];
        
        for(char c : s.toCharArray()) {
            cnt[c - 'a']++;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 26; i++) {
            if (cnt[i] == 1) sb.append((char)i+'a');
        }
        return sb.toString(); 
    }
}

위 코드에서 메서드를 따로 분리하면 아래와 같이 재사용성이 높은 코드가 된다.

class Solution {
    public String solution(String my_string, int[][] queries) {
        StringBuilder sb = new StringBuilder(my_string);

        // 각 쿼리에 대해 부분 문자열을 뒤집기
        for (int[] query : queries) {
            int s = query[0];
            int e = query[1];
            reverse(sb, s, e);  // 구간 [s, e]를 뒤집는 메서드 호출
        }

        return sb.toString();
    }

    //특정 구간을 뒤집는 메서드 (swap 반복 사용)
    private void reverse(StringBuilder sb, int start, int end) {
        while (start < end) {
            swap(sb, start, end);  // 두 문자 위치 교환
            start++;
            end--;
        }
    }

    // 두 인덱스의 문자를 교환하는 메서드
    private void swap(StringBuilder sb, int i, int j) {
        char temp = sb.charAt(i);
        sb.setCharAt(i, sb.charAt(j));
        sb.setCharAt(j, temp);
    }
}


오답

처음에는 문자 두 개를 바꾸는 swap() 메서드를 별도로 구현했으나, 이것 만으로는 로직 구현이 어렵다.

private void swap(StringBuilder sb, int i, int j) {
    char temp = sb.charAt(i);
    sb.setCharAt(i, sb.charAt(j));
    sb.setCharAt(j, temp);
}

특정 구간을 뒤집는 reverse() 메서드를 구현해서 시작 범위부터 끝 범위까지 반복되는 작업을 수행할 수 있도록 해야 한다.

private void reverse(StringBuilder sb, int start, int end) {
    while (start < end) {
        swap(sb, start, end); 
        start++;
        end--;
    }
}

✅ for (int[] query : queries)
✅ sb.setCharAt(i, sb.charAt(j));
sb.setCharAt(i, sb.charAt(j));

메서드 이름

설명

sb.charAt(j)

j번째 문자를 가져옴 (읽기)

sb.setCharAt(i, ...)

i번째 위치에 문자를 덮어씀 (쓰기)

위 메서드의 사용법은 아래와 같다.

StringBuilder sb = new StringBuilder("hello");
sb.setCharAt(1, sb.charAt(4));  // 'e' → 'o'
System.out.println(sb); // 출력: "hollo"

setCharAt(i, sb.charAt(j))는 단순히 i번째 값을 j번째로 복사하는 것이기 때문에, 이 문제에서 요구한 문자 교환(swap) 을 하려면 임시 저장 변수(temp)를 사용해야 한다.




6. [Java] 약수구하기 - list.toArray(new String[0]);

https://school.programmers.co.kr/learn/courses/30/lessons/120897

오답

import java.util.*;

class Solution {
    public int[] solution(int n) {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            if(n%i==0) list.append(i);
        }
        int[] answer = list.toArray(new String[0]);
        return answer;
    }
}

image.png

✅ for (int i = 0; i <= n; i++)
✅ list.add(i)
✅ int[] answer = list.toArray(new String[0]);


개선한 코드

import java.util.*;

class Solution {
    public int[] solution(int n) {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            if(n%i==0) list.add(i);
        }
        int[] answer = new int[list.size()];
        for(int i = 0; i < list.size(); i++) {
            answer[i] = list.get(i);
        }
        return answer;
    }
}


Stream 사용 버전

import java.util.*;
import java.util.stream.*;

class Solution {
    public int[] solution(int n) {
        return IntStream.rangeClosed(1, n) // 1부터 n까지 숫자 생성
                .filter(i -> n % i == 0)   // 약수만 필터링
                .toArray();                // int[]로 반환
    }
}




List → Array 형변환

List 타입

변환 방법

List<String>

list.toArray(new String[0])

List<Integer>

list.toArray(new Integer[0])

List<Integer>int[]

반복문으로 수동 변환 필요


✅ 1. List → Array (참조형, 예: Integer, String 등)
List<String> list = Arrays.asList("a", "b", "c");
String[] arr = list.toArray(new String[0]);
List<Integer> list = Arrays.asList(1, 2, 3);
Integer[] arr = list.toArray(new Integer[0]);


✅ 2. List → Array (기본형, 예: int)
List<Integer> list = Arrays.asList(1, 2, 3);
int[] arr = new int[list.size()];

for (int i = 0; i < list.size(); i++) {
    arr[i] = list.get(i);  // 언박싱 자동 수행
}




Array → List 형변환


변환 방법

String[]

Arrays.asList(arr)

Integer[]

Arrays.asList(arr)

int[]

Arrays.stream(arr).boxed().collect(Collectors.toList())


✅ 1. 참조형 배열 → List (예: String[], Integer[] 등)
String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);
List<String> modifiableList = new ArrayList<>(Arrays.asList(arr));


✅ 2. 기본형 배열 → List (예: int[], double[] 등)
int[] arr = {1, 2, 3, 4};

List<Integer> list = Arrays.stream(arr)  // IntStream 생성
                           .boxed()      // int → Integer (박싱)
                           .collect(Collectors.toList());



7. [Java] 가장 큰 수 찾기- return new int[]{max, idx};

https://school.programmers.co.kr/learn/courses/30/lessons/120899

오답

import java.util.*;

class Solution {
    public int[] solution(int[] array) {
        Arrays.sort(array);
        int[] answer = new int[2];
        answer[0] = array[array.length-1];
        answer[1] = array.length-1;
        return answer;
    }
}

image.png

✅ index 계산 잘못됨


개선한 코드

import java.util.*;

class Solution {
    public int[] solution(int[] array) {
        int max = array[0];
        int idx = 0;
        
        for(int i = 1; i < array.length; i++) {
            if (array[i] > max) {
                max = array[i];
                idx = i;
            }
        }
        return new int[]{max, idx};
    }
}


배열 리터럴을 반환할 때 쓰는 코드

int형 두 개짜리 배열을 직접 생성하고, 그 배열을 메서드의 반환값으로 사용하는 코드이다.

return new int[]{max, idx};

아래와 같이 배열을 만들고 반환하는 코드인데 한 줄로 줄인 것이다.

int[] result = new int[]{max, idx};
return result;

Java에서 return은 값을 반환하기만 하면 되기 때문에, 굳이 int[] result = ...처럼 중간에 변수에 담을 필요가 없다.


배열 리터럴은 선언 없이 쓰면 컴파일 오류가 난다.

int[] a;
a = {1, 2}; // ❌ 컴파일 오류

→ 대신 이렇게 써야 한다.

int[] a = new int[]{1, 2};



8. [Java] 문자열 계산하기 - Character.isDigit(c)

https://school.programmers.co.kr/learn/courses/30/lessons/120902

틀린 코드 (1차 시도)

class Solution {
    public int solution(String my_string) {
        char[] arr = my_string.toCharArray();
        int sum = 0;
        for (char c : arr ) {
            if (c != '+' && c != '-' && c !=' ') {
                sum+= Integer.parseInt(c);
            }
        }
        return sum;
    }
}

image.png

✅ Integer.parseInt()


String → int VS char → int

1. String을 int로 변환할 때는 Integer.parseInt()

String str = "123";

// 문자열 → int
int num = Integer.parseInt(str);       // 123

2. char을 숫자로 변환할 때는 char 타입 변수 - '0'

char c = '7';

// 문자 → 숫자 (정수값)
int digit = c - '0';   // '7' - '0' = 7


틀린 코드 (2차 시도)

class Solution {
    public int solution(String my_string) {
        char[] arr = my_string.toCharArray();
        int sum = 0;
        for (char c : arr ) {
            if (c != '+' && c != '-' && c !=' ') {
                sum+= c - '0';
            }
        }
        return sum;
    }
}

image.png

내가 쓴 코드는 모든 숫자를 "한 자리 숫자"로 처리한다. 즉, "12"가 있으면 1 + 2 = 3으로 계산한다.

String my_string = "a12b3";
→ arr = ['a', '1', '2', 'b', '3']
→ 결과: 1 + 2 + 3 = 6 (❗ 실제 12 + 3이 아님)

문제에서 원하는 것은 만약 "12 + 3" → 15로 계산하는 것이다.

String num 변수를 밖으로 빼고, Character.isDigit() 으로 c가 0~9사이 숫자형 문자열이면 num에 저장하는 형식으로 코드를 짜 주었다.


틀린 코드 (3차 시도)

class Solution {
    public int solution(String my_string) {
        char[] arr = my_string.toCharArray();
        int sum = 0;
        String num = "";
        for (char c : arr ) {
            if (Character.isDigit(c)) {
                num += c;
            } else {
                if (!num.isEmpty()) {
                    sum += Integer.parseInt(num);
                    num = ""; 
                }
            }
        }
        if (!num.isEmpty()) {
            sum += Integer.parseInt(num);
        }
        return sum;
    }
}

image.png

덧셈만 하는게 아니라 뺄셈도 있었다. 연산자(+, -)에 따라 연산을 모두 처리하는 코드를 짜야 한다.

  1. 문자열을 " "(공백) 기준으로 나눠서
  2. 처음 값은 result에 저장
  3. 이후에는 연산자(+ 또는 -)와 숫자가 번갈아 등장
  4. 연산자에 따라 +면 더하고, -면 빼야 함


틀린 코드 (4차 시도)

class Solution {
    public int solution(String my_string) {
        String[] splited = my_string.split(" ");
        int answer = Integer.parseInt(splited[0]);
        
        for(int i = 1; i < splited.length; i += 2) {
            String op = splited[i];
            int num = Integer.parseInt(splited[i + 1]);
            
            if (op == '+')) {
                answer += num;
            } else if (op == '-') {
                answer -= num;
            }
        }
        return answer;
    }
}
✅ if(op == '+')


개선한 코드

class Solution {
    public int solution(String my_string) {
        String[] splited = my_string.split(" ");
        int answer = Integer.parseInt(splited[0]);
        
        for(int i = 1; i < splited.length; i += 2) {
            String op = splited[i];
            int num = Integer.parseInt(splited[i + 1]);
            
            if (op.equals("+")) {
                answer += num;
            } else if (op.equals("-")) {
                answer -= num;
            }
        }
        return answer;
    }
}



9. [Java] 배열의 유사도(배열, Set) - set.contains(str)

https://school.programmers.co.kr/learn/courses/30/lessons/120903

Set 을 활용한 코드

import java.util.*;

class Solution {
    public int solution(String[] s1, String[] s2) {
        Set<String> set = new HashSet<>(Arrays.asList(s1));
        int cnt = 0;
        for (String str : s2) {
            if (set.contains(str)) cnt++;
        }
        return cnt; 
    }
}


✅ Set<String> set = new HashSet<>(Arrays.asList(s1));


이중 for문(반복문)을 사용한 코드

class Solution {
    public int solution(String[] s1, String[] s2) {
        int cnt = 0;
        for (int i = 0; i < s1.length; i++) {
            for (int j = 0; j < s2.length; j++) {
                if (s1[i].equals(s2[j])) {
                    cnt++;
                    break;
                }
            }
        }
        return cnt;
    }
}


10. [Java] 숫자 찾기 - String.indexOf(), String.valueOf()

https://school.programmers.co.kr/learn/courses/30/lessons/120904

오답

class Solution {
    public int solution(int num, int k) {
        String numToString = Integer.toString(num);
        char[] arr = numToString.toCharArray();
        char kToChar = (char) k; 
        int idx = -1;
        for(int i = 0; i < arr.length; i++ ) {
            if (arr[i] == kToChar) {
                return i+1;
            }
        }
        return idx;
    }
}
✅ char kToChar = (char) (k + '0');

개선한 코드

class Solution {
    public int solution(int num, int k) {
        String numToString = Integer.toString(num);
        char[] arr = numToString.toCharArray();
        char kToChar = (char) (k + '0');
        int idx = -1;
        for(int i = 0; i < arr.length; i++ ) {
            if (arr[i] == kToChar) {
                return i+1;
            }
        }
        return idx;
    }
}


더 간단한 방법 (String API 활용)

public int solution(int num, int k) {
    String s = String.valueOf(num);
    int idx = s.indexOf(String.valueOf(k));
    return idx == -1 ? -1 : idx + 1;
}


✅ String.indexOf()

문자열 내에서 특정 문자나 문자열이 처음 등장하는 위치의 인덱스를 알려주는 매우 유용한 메서드이다.

📌 기본 사용법

String s = "29183";
int idx = s.indexOf("1");   // 결과: 2

📌 자바 공식 문법

int indexOf(int ch)           // 문자 또는 문자 코드 (ex: 'a', 97)
int indexOf(String str)       // 문자열


✅ 삼항연산자

자바의 삼항 연산자(ternary operator)는 if-else를 한 줄로 간단하게 쓸 수 있게 해주는 조건 연산자이다.

📌 기본 사용법

조건식 ? 참일 때 값 : 거짓일 때 값;

📌 예제

int age = 20;
String result = (age >= 18) ? "성인" : "미성년자";
System.out.println(result);  // 출력: 성인



11. [Java] 삼각형의 완성조건(2): case2는 왜 longer - shorter인가?


https://school.programmers.co.kr/learn/courses/30/lessons/120868


정수 범위 공식

정답 코드

import java.util.*;
 
class Solution {
    public int solution(int[] sides) {
        Arrays.sort(sides); // 배열 오름차순 정렬
        int shorter = sides[0];
        int longer = sides[1];
        
        // case1: x가 가장 긴 변일 때 -> x < a + b
        int case1 = longer + shorter - 1; 
        
        // case2: x가 짧거나 중간인 경우 -> x > max - min
        int case2 = longer - shorter;
        
        return case1 - case2;
    }
}

case2가 longer - shorter + 1이 아니라 longer - short인 이유

예시


12. [Java] 옹알이(1): break vs continue

https://school.programmers.co.kr/learn/courses/30/lessons/120956


1. 전체 코드

import java.util.*;

class Solution {
    public int solution(String[] babbling) {
        String[] canSay = {"aya", "ye", "woo", "ma"};
        int count = 0;

        for (String word : babbling) {
            String temp = word;
            boolean isValid = true;

            for (String say : canSay) {
                // 중복된 발음이 있는지 확인
                if (temp.contains(say + say)) {
                    isValid = false;
                    break;
                }
            }

            if (!isValid) continue;

            // 발음 가능 단어 제거
            for (String say : canSay) {
                temp = temp.replace(say, " ");
            }

            // 모두 제거되었는지 확인 (공백만 남은 경우 trim()으로 제거)
            if (temp.trim().isEmpty()) {
                count++;
            }
        }

        return count;
    }
}

2. 같은 단어 중복인지 확인하는 코드

if (temp.contains(say + say)) {
    isValid = false;
    break;
}

3. continue

for (String word : babbling) {
    // 어떤 조건으로 유효한 발음인지 검사
    if (!isValid) continue;

    // 여기 있는 코드는 건너뜀!
}

4. break

for (String say : canSay) {
    if (temp.contains(say + say)) {
        isValid = false;
        break; // ✅ 이 for 루프를 빠져나옴!
    }
}

여기서 break;는 바로 canSay 배열을 순회하는 for문을 탈출한다.

따라서 그 다음 실행되는 건 → continue; 실행됨 → 이 단어는 skip하고 다음 단어로 넘어가는 로직이 실행된다.

if (!isValid) continue;

5. continue VS break

for each word in babbling:
    for each say in canSay:
        if word contains say+say:
            isValid = false
            break ← 여기서 안쪽 for문 탈출
    if (!isValid) continue ← 이 줄로 와서 현재 word 스킵



13. [Java] 배열만들기4: stack → int[] 변환

https://school.programmers.co.kr/learn/courses/30/lessons/181918?language=java

1. 전체 코드

import java.util.*;

class Solution {
    public int[] solution(int[] arr) {
        Stack<Integer> stk = new Stack<>();
        int i = 0;
        
        while (i < arr.length) {
            if (stk.isEmpty()) {
                stk.push(arr[i]);
                i++;
            } else if (stk.peek() < arr[i]) {
                stk.push(arr[i]);
                i++;
            } else {
                stk.pop();
            }
        }
        
        // stack → int[]
        int[] answer = new int[stk.size()];
        for (int j = 0; j < stk.size(); j++) {
            answer[j] = stk.get(j);
        }
        return answer;
    }
}

2. for문 으로 stack → int[] 변환

// stack → int[]
int[] answer = new int[stk.size()];
for (int j = 0; j < stk.size(); j++) {
    answer[j] = stk.get(j);
}
return answer;

3. stream() 으로 stack → int[] 변환

// stream을 이용한 stack → int[] 변환
return stk.stream().mapToInt(Integer::intValue).toArray();

4. 속도 비교

테스트 케이스 크기

for-loop

stream

100개

약 0.01ms

약 0.01ms

100,000개

약 1.5ms

약 2.2ms

1,000,000개

약 15ms

약 22ms

차이 있음: 데이터가 클수록 stream()이 약간 느림
하지만 일반적인 코테에서는 이 정도 차이는 오답 판정으로 이어질 정도는 아님




14. [Java] 주사위 게임 3

https://school.programmers.co.kr/learn/courses/30/lessons/181916

1. 주사위 점수 계산 조건

  1. 네 주사위가 모두 같을 경우
  1. 세 개가 같고 하나가 다를 경우
  1. 두 개씩 같은 숫자가 나올 경우
  1. 한 쌍과 나머지 두 숫자가 각각 다를 경우
  1. 모두 다른 숫자가 나올 경우

2. 전체 코드

import java.util.*;

class Solution {
    public int solution(int a, int b, int c, int d) {
        int[] dice = {a, b, c, d};
        Map<Integer, Integer> count = new HashMap<>();
        
        // 빈도 계산
        for (int num : dice) {
            count.put(num, count.getOrDefault(num, 0) + 1);
        }

        int size = count.size();
        List<Integer> keys = new ArrayList<>(count.keySet());

        if (size == 1) {
            // case 1: 네 개 모두 같은 수
            int p = keys.get(0);
            return 1111 * p;

        } else if (size == 2) {
            Collection<Integer> freqs = count.values();
            if (freqs.contains(3)) {
                // case 2: (p, p, p, q)
                int p = 0, q = 0;
                for (int key : keys) {
                    if (count.get(key) == 3) p = key;
                    else q = key;
                }
                return (int) Math.pow(10 * p + q, 2);
            } else {
                // case 3: (p, p, q, q)
                int p = keys.get(0);
                int q = keys.get(1);
                return (p + q) * Math.abs(p - q);
            }

        } else if (size == 3) {
            // case 4: (p, p, q, r)
            int result = 1;
            for (int key : keys) {
                if (count.get(key) == 1) result *= key;
            }
            return result;

        } else {
            // case 5: 모두 다름
            return Arrays.stream(dice).min().getAsInt();
        }
    }
}

Map 쓰는 이유?

문제에서 "같은 숫자가 몇 개 나왔는지"를 기준으로 조건이 분기됨

문제 조건 다시 보면:

즉, "각 숫자가 몇 번 나왔는지"를 기준으로 판단해야 한다.
이 말은 곧 "숫자 → 빈도 수"를 빠르게 셀 수 있는 구조가 필요하다는 뜻이다.

그래서 Map<Integer, Integer> 구조가 적절하다. Map은 키(숫자)마다 몇 번 나왔는지(빈도)를 저장할 수 있어서 조건 분기문(예: if (count.size() == 2) 등)을 짜기 매우 직관적이다.

물론 이 문제에서는 숫자가 1~6 범위로 작고, 고정이므로 빈도 배열 int[7] freq도 가능하다.

예를 들어:

int[] freq = new int[7];
freq[a]++;
freq[b]++;
freq[c]++;
freq[d]++;

→ 숫자가 1~6로 제한되어 있다는 걸 사전에 알 때만 배열이 가능하고, 그 외 범위에서는 Map이 더 일반적이고 확장성 있다.

언제 Map을 써야 하는가?

“값 → 등장 횟수” 구조가 필요할 때 Map을 쓴다. 즉, Map은 "무엇이 얼마나 나왔는가"라는 질문에 답해야 할 때 가장 먼저 떠올려야 할 자료구조이다. 특히 문제에서 값의 개수, 빈도, 중복 여부가 중요한 역할을 한다면, Map은 거의 정답에 가깝다고 보면 된다.

 프로그래머스에서 좋아요 제일 많이 받은 코드

장홍범 , flao1 , plotojjy@gmail.com , sksmsgla2@gmail.com 외 146 명
import java.util.Arrays;

class Solution {
    public int solution(int a, int b, int c, int d) {

        int[] dice = { a, b, c, d };
        Arrays.sort(dice);

        int ans = 0;

        if (dice[0] == dice[3]) {
            ans = 1111 * dice[3];
        } else if (dice[0] == dice[2] || dice[1] == dice[3]) {
            ans = (int) Math.pow(dice[1] * 10 + (dice[0] + dice[3] - dice[1]), 2);
        } else if (dice[0] == dice[1] && dice[2] == dice[3]) {
            ans = (dice[0] + dice[3]) * (dice[3] - dice[0]);
        } else if (dice[0] == dice[1]) {
            ans = dice[2] * dice[3];
        } else if (dice[1] == dice[2]) {
            ans = dice[0] * dice[3];
        } else if (dice[2] == dice[3]) {
            ans = dice[0] * dice[1];
        } else {
            ans = dice[0];
        }

        return ans;
    }
}





15. [Java] 9로 나눈 나머지


https://school.programmers.co.kr/learn/courses/30/lessons/181914

오답

class Solution {
    public int solution(String number) {
        int answer = 0;
        int sum = 0;
        for (int i = 0; i < number.length(); i++) {
            sum += number.charAt(i);
        }
        answer = sum % 9;
        return answer;
    }
}
image.png

위 코드에서 틀린 부분은 number을 순회하면서 sum변수에 누적하는 과정이다.

sum += number.charAt(i);
sum += number.charAt(i) - '0';

개선한 코드

class Solution {
    public int solution(String number) {
        int answer = 0;
        int sum = 0;
        for (int i = 0; i < number.length(); i++) {
            sum += number.charAt(i) - '0';
        }
        answer = sum % 9;
        return answer;
    }
}

image.png