포스트

[Java] 프로그래머스 - Java 기초

[Java] 프로그래머스 Java 기초 문제 풀이 과정을 정리한 글입니다.

For the English version of this post, see here.
[Java] 프로그래머스 - Java 기초

몫 구하기

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

Java에서 몫을 구하기 위해서는 /를 사용해야한다.

정수 / 정수 → 정수값 몫을 반환하는데

실수 / 정수 → 와 같이 하나라도 실수라면 실수값 몫을 제공한다.

Java에서 //기호는 주석을 의미하기 때문에 Python에서와 같이 //로 몫을 구할 수 없다.

분수의 덧셈

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
        int[] answer = new int[2];
        
        answer[0] = numer1*denom2 + numer2*denom1;
        answer[1] = denom1 * denom2;
        
        while(answer[0] != 1) {
            for(int i = answer[1]; i>=1; i--) {
                if (answer[0] % i == 0 && answer[1] % i == 0) {
                    answer[0] /= i;
                    answer[1] /= i;
                
                }
            }
        }
        
        return answer;
    }
}
  • 처음 코드의 오류
    • 기약 분수가 된다고 해서, 분자가 다 1이 되는 것은 아니다.
      • 분자가 1이 아니라도 기약 분수가 되면 반복을 종료하도록 해야한다.
    • 약분하려면 분자와 분모 중 더 작은 값을 찾는 것이 우선이다.

    • 또한, 분모 수에서 1까지 반복하는 for문에서 1은 약분에서 의미가 없으므로 확인할 필요가 없다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
      class Solution {
          public int[] solution(int numer1, int denom1, int numer2, int denom2) {
              int[] answer = new int[2];
                
              answer[0] = numer1*denom2 + numer2*denom1;
              answer[1] = denom1 * denom2;
                
              for(int i = Math.min(answer[0], answer[1]); i>=2; i--) {
                  if (answer[0] % i == 0 && answer[1] % i == 0) {
                      answer[0] /= i;
                      answer[1] /= i;
                      break;
                  }
              }
                
              return answer;
          }
      }
    
  • 수정 후 코드
    • 최대공약수로 한 번만 나누면 기약분수가 됨 → while문이 필요 없다.

    • Math.min() 을 사용 → 분자와 분모 중 작은 값 반환

중앙값 구하기

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

  • Java에서의 배열

    • 배열 선언

      1
      
        int[] arr;
      
    • 배열 생성

      1
      
        int[] arr = new int[5];
      
    • 배열 선언과 동시에 초기화

      1
      
        int[] arr = {10, 20. 30, 40, 50};
      
    • 배열 길이 확인

      1
      2
      
        len = arr.length;
        System.out.println(arr.length);
      
    • 배열 정렬

      • Arrays.sort() 메서드 사용

        1
        2
        3
        4
        5
        6
        7
        8
        
          import java.util.Arrays;
        
          int[] arr = {5, 2, 8, 1, 3};
        
          Arrays.sort(arr);
        
          System.out.println(Arrays.toString(arr));
          // [1, 2, 3, 5, 8]
        
        • Arrays.sort(arr); → 배열을 오름차순으로 정렬

        • Arrays.toString(arr) → 배열의 요소를 문자열 형태로 출력

          • 그냥 System.out.println(arr);을 사용하면 → 배열의 요소가 아니라 배열의 타입과 해시코드를 나타내는 문자열이 출력됨

            1
            
              [I@15db9742
            
          1
          2
          3
          4
          5
          6
          7
          8
          9
          
            import java.util.Arrays;
            import java.util.Collections;
          
            Integer[] arr = {5, 2, 8, 1, 3};
          
            Arrays.sort(arr, Collections.reverseOrder());
          
            System.out.println(Arrays.toString(arr));
            // [8, 5, 3, 2, 1]
          
        • Arrays.sort(arr, Collections.reverseOrder());
          → 내림차순 정렬

          • Collections.reverseOrder() → 내림차순 정렬에 사용되는 비교 기준
        • int[]가 아닌 Integer[] 배열을 사용해야한다.

          💡

          int[]는 기본 자료형 배열 Integer[]는 참조 자료형 배열

          • Integer는 int를 객체로 다루기 위한 래퍼 클래스

          • Integer[]는 Integer 객체의 참조를 저장하는 배열

          → Collections.reverseOrder() 는 객체를 비교하는 Comparator를 반환한다. 따라서 Arrays.sort(배열, Comparator)는 객체 배열에만 사용할 수 있어서 int[]에는 적용할 수 없다.

최빈값 구하기

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

내 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
    public int solution(int[] array) {
        int[] answer = new int[1000];
        
        for(int i = 0; i<array.length; i++) {
            
            answer[array[i]] += 1;
        }
        
        int[] max = new int[3]; // 0: max 값 1: max 인덱스 2: 그 전 max 값
        max[0] = 0;
        
        for(int i = 0; i<answer.length; i++) {
            if(answer[i] > max[0]) {
                max[0] = answer[i];
                max[2] = answer[i];
                max[1] = i;
            } else if (answer[i] == max[0]) {
                max[2] = -1;
            }
        }
        
        if (max[2] != -1) {
            return max[1];
        } else {
            return -1;
        }
    }
}

더 나은 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
    public int solution(int[] array) {
        int[] count = new int[1000];

        for (int num : array) {
            count[num]++;
        }

        int max = 0;
        int answer = 0;

        for (int i = 0; i < count.length; i++) {
            if (count[i] > max) {
                max = count[i];
                answer = i;
            } else if (count[i] == max) {
                answer = -1;
            }
        }

        return answer;
    }
}
  • 향상된 for문 사용
    for(int num : array)를 사용해 배열의 요소를 하나씩 꺼내서 num에 대입

  • max 배열 대신 변수 사용

    • 별도의 중복 확인을 위해 배열을 만들었었는데, 필요하지 않기 때문에 변수로 바로 최빈값 확인 가능

    • 끝까지 for문을 돌면서 최빈값이 중복되면 -1, 저장해둔 max 값보다 새로운 값이 더 크면 다시 최빈값으로 저장

다른 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.HashMap;

class Solution {
    public int solution(int[] array) {
        HashMap<Integer, Integer> map = new HashMap<>();

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

        int max = 0;
        int answer = 0;

        for (int num : map.keySet()) {
            int count = map.get(num);

            if (count > max) {
                max = count;
                answer = num;
            } else if (count == max) {
                answer = -1;
            }
        }

        return answer;
    }
}
  • HashMap 활용
    문제에서는 배열을 사용하는 게 더 간단하지만, 숫자의 범위가 크거나 음수가 포함된다면 HashMap을 사용하는 방법도 있음

    map.put(num, map.getOrDerfault(num, 0) + 1); → getOrDefault(num, 0)은 해당 숫자가 이미 저장되어 있으면 기존 등장 횟수를 가져오고, 없으면 0을 반환한다.

짝수는 싫어요

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

풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList;
import java.util.Arrays;

class Solution {
    public int[] solution(int n) {
        ArrayList<Integer> array = new ArrayList<>();
        
        for(int i = 1; i<=n; i++) {
            if(i%2 != 0) {
                array.add(i);
            }
        }
        
        int[] answer = array.stream().mapToInt(Integer::intValue).toArray();
        
        return answer;
    }
}

answer에 배열을 반환해야 하는데, 문제를 풀면서 배열에 몇 개의 값이 들어갈지 모르기 때문에 ArrayList를 사용했다.

  • ArrayList
    • Java에서 제공하는 크기가 동적으로 변하는 배열 기반의 자료구조

    • 처음에 요소의 개수를 지정하지 않아도 됨
      • 요소 추가하면 필요에 따라 내부 저장 공간이 자동으로 확장됨
    • arr.size()로 요소 개수 확인

    • int, double 같은 기본 자료형을 타입 인자로 사용할 수 없음
      • int 대선 래퍼 클래스인 Integer를 사용함
  • int[] answer = array.stream().mapToInt(Integer::intValue).toArray();
    • stream() → 리스트의 요소를 순서대로 처리할 수 있도록 Strem 생성

    • mapToInt(Integer::intValue) → Integer 객체들을 기본 자료형 int 값으로 변환

    • toArray() → 변환된 값들을 배열에 담아 반환

    💡
    • ArrayList로 선언
      ArrayList<Integer> array = new ArrayList<>();

    → 변수 타입: ArrayList , 실제 생성 객체: ArrayList

    • List로 선언
      List<Integer> array = new ArrayList<>();

    → 변수 타입: List , 실제 생성 객체: ArrayList

    ⇒ List는 인터페이스이고, ArrayList는 List 인터페이스를 구현한 클래스

    image

    • List로 선언하는 이유
      List<Integer> array = new ArrayList<>();로 선언했다가 나중에 LinkedList로 변경하고 싶다면 → List<Integer> array = new LinkedList<>(); 로 객체를 생성하는 부분만 변경하면 됨 (물론 LinkedList도 별도로 import 해야함)

    ⇒ 따라서, 일반적으로 변수는 인터페이스 타입으로 선언하고, 실제 객체는 구현 클래스로 생성하는 방식을 사용함

뒤집힌 문자열

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

Java 문자열

  • 문자열 선언 및 초기화
    String str = "Hello"; String str2 = new String("Hello");

  • String과 char의 차이 image

  • 문자열 관련 주요 메서드 image

  • 문자열 연결
    Java에서는 + 연산자를 사용해 문자열을 연결할 수 있다.

  • 문자열 비교
    문자열의 내용을 비교할 때는 equals()를 사용해야한다.

    ==를 사용하지 못하는 이유 → 두 변수가 같은 객체를 참조하는지 주소를 비교하기 때문

  • 문자열은 불변 객체
    Java의 String은 한 번 생성하면 객체의 내용을 변경할 수 없다.

    1
    2
    3
    4
    5
    
      String str = "Hello";
    
      str.replace("H", "J");
    
      System.out.println(str); // Hello
    

    → replace()는 원본 문자열을 수정하는 것이 아니라 새로운 문자열을 반환한다.

    1
    2
    3
    
      str = str.replace("H", "J");
    
      System.out.println(str); // Jello
    

외계행성의 나이

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

풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
    public String solution(int age) {
        String answer = "";
        
        String alpha = "abcdefghij";
        
        String str = String.valueOf(age);
        
        for (int i = 0; i < str.length(); i++) {
            int num = str.charAt(i) - '0';
            answer += alpha.charAt(num);
        }
        
        return answer;
    }
}
  • 숫자를 문자열로 변환
    String str = String.valueOf(age); → 숫자를 문자열로 변환해 charAt()을 이요해 각 자릿수에 접근할 수 있게됨

  • 문자를 숫자로 변환
    int num = str.charAt(i) - '0'; → charAt()은 char 타입을 반환함 ⇒ 필요한 건 정수형 숫자 인덱스! → Java에서 문자끼리 빼기 연산을 하면 유니코드 값을 기준으로 계산해주기 때문에 ‘2’ - ‘0’과 같이 숫자 문자를 정수로 변환해줌

댓글

궁금한 점, 피드백, 오류 제보를 남겨 주세요.