728x90
 

[실전 알고리즘] 0x03강 - 배열

안녕하세요, 바킹독입니다.. 저번 단원의 내용인 코드 작성 요령 II는 순한 맛이었는데 오늘건 그냥 단맛입니다. 난이도가 굉장히 낮으니 긴장 푸시고 강의로 들어가겠습니다. 목차는 따로 설명

blog.encrypted.gg

 

해당 블로그 내의 강의를 자바 언어로 풀면서 학습한 내용을 정리하고 있습니다.

 

int[] numbers = {1, 23, 53, 77, 60};

 

우선 0 ~ 100까지의 숫자를 랜덤으로 가진 배열이 주어진다.

 

주어진 배열에서 두 수를 더해 합이 100이 되는 경우가

존재하면 1, 존재하지 않으면 2를 출력하는 문제로

 

가장 단순하게 생각하면 배열의 특정 요소와 나머지 요소를 모두

번갈아가며 비교하여 100이 되는 경우가 있는지 확인하는 방법이 있다.

 

단순하지만 시간복잡도가 효율적인 방법은 아니기 때문에

더 좋은 방법은 새로운 배열을 만들어 기록하는 방법이다.

 

int[] save = new int[101];

 

위와 같이 0 ~ 100까지의 숫자가 출현했는지 여부를 기록할

배열을 0으로 초기화 시켜두고

숫자가 등장하면 해당 값의 등장 여부를 1로 기록한다.

 

for (int number : numbers) {

    if (save[100 - number] == 1 || number == 100) {
        System.out.println(1);
        return;
    }
    save[number] = 1;
}

System.out.println(0);

 

현재 숫자와 더해 100이 될 수 있는 값이 이전에 등장했거나 현재 숫자가 100이라면

합이 100인 경우가 존재하는 것을 알 수 있기 때문에

1을 출력하고 존재하지 않는다면 0을 출력하면 된다.

 

중복된 계산을 해야하는 경우에는 배열 같은 자료구조를 이용해

계산 결과를 저장하여 중복된 계산을 피하는 방식이 효율적이다.

'Java > Algorithms' 카테고리의 다른 글

[백준] 1475번 : 방 번호  (0) 2023.09.28
[백준] 2577번 : 숫자의 개수  (0) 2023.09.28
[백준] 2292번 : 벌집  (0) 2023.07.30
[백준] 2720번 : 세탁소 사장 동혁  (0) 2023.07.30
[백준] 2903번 : 중앙 이동 알고리즘  (0) 2023.07.30
728x90

현재 위치 1을 포함하여 N까지 가기 위한 최단 경로를 구하는 문제다.

 

벌집은 6각형으로 이루어져있으니

밖으로 한 층 나갈 때마다 6의 배수만큼 방의 개수가 증가한다

 

아래와 같이 방의 개수가 증가한다.

1 + 6 = 7

7 + 12 = 19

19 + 18 = 37

...

 

즉 최단 경로만 구하면 되는 문제이기 때문에

한 층씩 나갈 때마다 현재 층에 N이라는 방이 있는지 확인만 하면 된다.

 

public class Main {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);

        int n = s.nextInt();

        int now = 1;
        int count = 1;

        while (now < n) {
            now += 6 * count;
            count++;
        }

        System.out.println(count);
    }
}

 

시작 위치는 항상 1이기 때문에 현재 위치를 1로 지정해주고

현재 위치도 이동한 것으로 포함하기 때문에 이동 횟수도 1부터 시작한다.

 

현재 위치한 층의 방이 n보다 작을 때까지 반복하며

방의 개수를 더해주다보면 반복문을 탈출한 시점의 층에 찾는 방이 있다.

728x90

핵심 키워드

동전, 최소

 

문제 요약

손님에게 거스름돈을 줄 때 동전의 개수를 최소로 하는 경우를 계산

그러기 위해선 가장 큰 단위의 동전부터 계산해야 함

 

문제 풀이

public class Main {
    public static void main(String[] args) {
        int[] charges = {25, 10, 5, 1};
        String[] count = new String[4];

        Scanner s = new Scanner(System.in);
        int test = s.nextInt();

        for(int i = 0; i < test; i++) {
            int cent = s.nextInt();

            count[0] = String.valueOf(cent/charges[0]);
            cent%=charges[0];
            count[1] = String.valueOf(cent/charges[1]);
            cent%=charges[1];
            count[2] = String.valueOf(cent/charges[2]);
            cent%=charges[2];
            count[3] = String.valueOf(cent/charges[3]);

            System.out.println(String.join(" ", count));
        }
    }
}

우선 동전의 종류 4가지를 배열에 저장할 때

단위는 입력의 단위에 맞춰서 저장한다. (0.25 >> 25)

 

테스트케이스의 수만큼 입력을 받고

이를 가장 큰 단위의 동전부터 거스름돈을 계산한다.

 

각각의 동전의 수를 출력한다.

728x90

https://www.acmicpc.net/problem/2903

 

2903번: 중앙 이동 알고리즘

상근이는 친구들과 함께 SF영화를 찍으려고 한다. 이 영화는 외계 지형이 필요하다. 실제로 우주선을 타고 외계 행성에 가서 촬영을 할 수 없기 때문에, 컴퓨터 그래픽으로 CG처리를 하려고 한다.

www.acmicpc.net

 

  1. 정사각형의 각 변의 중앙에 점을 하나 추가한다.
  2. 정사각형의 중심에 점을 하나 추가한다.

정사각형에 위의 중앙 이동 알고리즘을 n번 적용하였을 때

추가된 점의 개수를 중복 없이 구하는 문제다.

 

개인적으로는 문제의 이해보다는 그림을 보고 규칙을 찾아서 풀었다.

 

주어진 그림 예시를 살펴보다 보니 

한 줄의 사각형의 수는 이전 사각형의 개수의 2배로 증가하는 규칙이 있다.

 

중앙 이동 알고리즘을 적용하기 전의 초기 상태는 사각형이 하나라면

그 뒤는 2 > 4 > 8 > 16 > 32 > ... 순서로 증가한다.

 

또한 한 줄에 찍히는 점의 수는

한 줄에 존재하는 사각형의 수  + 1이고

가로와 세로 상관 없이 찍히는 점의 수는 같으니

(한 줄에 존재하는 사각형의 수  + 1)의 제곱이

중복을 제외한 점의 수가 된다.

 

public class Main {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);

        int n = s.nextInt();

        int count = 1;

        for(int i = 0; i < n; i++) {
            count *= 2;
        }

        System.out.println((count + 1)*(count + 1));
    }
}
728x90

n개의 문자열 입력에 대한 그룹 단어 체크 프로그램 작성하기

(각각의 문자열은 소문자로만 구성되고 중복되지 않으며 최대 길이는 100)

 

그룹 단어의 조건

  • 각각의 알파벳은 연속되게 하나 이상 존재할 수 있다.
  • 연속되지 않고 끊어져서 동일한 알파벳이 존재할 수는 없다.
  • "aabbaa" 같은 경우는 그룹 단어가 아니다.
  • "aabbcc" 같은 경우는 그룹 단어가 맞다.

나의 풀이

public class Main {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);

        int n = s.nextInt();
        int count = 0;

        for (int i = 0; i < n; i++) {
            String str = s.next();
            String[] arr = str.split("");

            Map<String, Long> abc = Arrays.stream(arr)
                    .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));

            Set<String> sets = abc.keySet();


            int size = sets.size();
            for(String set : sets) {
                int start = str.indexOf(set);
                int end = str.lastIndexOf(set) + 1;
                
                if (end - start != abc.get(set)) {
                    break;
                }
                
                size--;
                
                if(size == 0) {
                    count++;
                }
            }
        }

        System.out.println(count);
    }
}
  1. 각각의 알파벳이 몇 번 등장하는지 카운팅
  2. 알파벳을 키로 카운팅을 값으로 가지는 맵에 저장
  3. 맵의 키의 개수만큼 반복문을 시작
  4. 문자열에 해당 알파벳이 등장하는 처음과 마지막 인덱스를 계산
  5. (마지막 인덱스 - 처음 인덱스) 가 알파벳의 카운팅과 일치하지 않는지 확인
  6. 일치하지 않으면 알파벳이 끊어져서 존재한다는 것과 같기 때문에 그룹 단어가 아니므로 반복문 탈출
  7. 일치하는 경우에는 해당 알파벳은 그룹 단어의 조건을 충족하니 통과
  8. 모든 알파벳이 통과되면 그룹 단어이기 때문에 카운트 증가
  9. 위의 방법을 입력의 수만큼 반복하며 그룹 단어 카운팅
  10. 최종 결과를 출력

새롭게 알게 된 내용

  • 종류별로 무언가를 계산하고 저장하고 싶을 때는 Map 자료구조를 사용하면 편리하다.
  • Collctors의 groupingBy 메서드를 사용하여 그룹별로 연산을 수행할 수 있다.
  • Function.identity 메서드를 사용해 각 요소를 그대로 그룹화 할 수 있다.
  • 해당 문제에서는 알파벳 별로 그대로 그룹화 할 때 사용하였다.
  • Collctors의 counting 메서드를 사용하여 각 그룹의 요소 개수를 카운트 할 수 있다.
  • 해당 문제에서는 각각의 알파벳의 수를 카운팅 했다.
728x90

 

Q1. 자바 데이터 타입 중 기본형과 참조형의 차이에 대해 설명해주세요.

 

Q2. 클래스와 객체에 대해 설명해주세요.

클래스는 객체를 생성할 때 사용되는 객체에 대한 정보를 가지고 있는 설계도이자 틀이고,

객체는 이러한 클래스를 통해 생성되는 인스턴스들을 의미합니다.

클래스는 내부에서 클래스의 속성을 정의하는 필드와 기능을 정의하는 메서드 등을 멤버로 가지고

이를 생성자를 통해 클래스의 멤버를 가진 인스턴스를 생성할 수 있습니다.

Q2-1. 클래스의 멤버에 대해 설명해주세요.

사람이라는 클래스로 비유하면

클래스의 멤버로는 우선 사람의 속성인 필드를 구성하는 인스턴스 변수와 클래스 변수가 있습니다.

인스턴스 변수는 (객체)사람마다 다른 속성인 이름이나 키, 성별 같은 것들을 정의하는 변수이고,

클래스 변수는 모든 사람이 공통적으로 동일하게 가지고 있는 속성을 정의하기 때문에

인스턴스를 따로 생성하지 않아도 클래스 변수에는 접근할 수 있지만, 인스턴스 변수는

인스턴스마다 값이 다르기 때문에 생성 후에 접근할 수 있습니다.

다음으로 메서드는 클래스의 기능을 정의합니다. 사람이 먹고 자고 일하는 그러한 동작들을 정의하는 멤버로

구현된 메소드는 클래스 영역에 있지만 객체와 메소드의 주소는 같은 힙 메모리 영역에 존재하기 때문에

같은 클래스로 만든 모든 객체들은 메서드를 한 번만 선언해주면 계속 사용할 수 있습니다.

마지막 멤버로는 외부 클래스와 내부 클래스의 관계를 구성하는 중첩 클래스가 있습니다. 외부 클래스를 가족,

내부 클래스를 구성원이라고 비유하면 가족 안에서도 요리, 빨래, 청소 등 구성원들마다 하는 역할이 정해져있듯이

클래스 안에서 관련된 기능과 데이터를 그룹화 해주는 역할을 담당하는 멤버입니다.

 

Q3. 생성자에 대해 설명해주세요.

 

Q4. 메서드 오버라이딩과 메서드 오버로딩의 차이는 무엇인가요?

둘은 명칭은 비슷하지만 완전히 다른 기능으로,

메서드 오버라이딩은 기존에 만들어져있는 메서드 혹은 완성되지 않은

추상 메서드를 새로 자신이 사용하고자 하는 형태로 기능을 구현하는 것이고,

메서드 오버로딩은 메서드가 전달 받는 매개변수의 타입 혹은 갯수를 달리하여

하나의 메서드를 다양한 경우로 활용하는 것을 말합니다.

비유하자면, 오버라이딩은 폴더에서 파일을 붙여넣기 할 때 이름이 같은 파일이 존재할 경우

새로운 파일로 덮어쓰는 것이고, 오버로딩은 switch 조건문처럼 주어진 조건에 따라 다른 문장을 실행하는 것입니다.

Q5. 자바의 메모리 영역에 대해 설명해주세요.

 

Q6. static 키워드에 대해 설명하고, static를 언제 사용해야 하는 지 설명해주세요.

 

Q7. 자바 객체지향 프로그래밍(OOP)에 대해 설명해주세요.

 

Q8. 자바 접근 제어자의 특징과 종류에 대해서 설명해주세요.

자바의 접근 제어자는 범위가 가장 넓은 순으로 public, protected, (default), private 총 4가지가 있습니다.

접근 제어자를 통해 객체 내부의 데이터를 외부에 직접적으로 노출시키지 않고 공개된 인터페이스를 통해서만

상호작용 하고 데이터를 무분별하게 수정하지 못하게 만들어줄 수 있습니다.

public은 패키지와 클래스 상관 없이 어느 곳에서든 접근할 수 있는 접근 상태이고,

protected는 동일한 패키지의 클래스와 해당 클래스를 상속 받은 외부 패키지의 클래스에서 접근할 수 있습니다.

default는 접근 제어자를 지정하지 않을시 기본적으로 설정되는 상태로, 동일한 패키지 내의 클래스에서만 접근 가능하며,

private은 동일한 클래스 내에서만 접근 가능하며, 해당 클래스를 상속 받았다 해도 접근할 수 없습니다.

즉, 외부에 노출되지 않고 데이터의 변경에 제한을 두고 싶은 경우에는 좁은 범위의 접근 제어자를 사용하고,

여러 곳에서 자주 사용되는 경우에는 넓은 범위의 접근 제어자를 사용합니다.

 

Q9. 추상 클래스와 인터페이스의 차이는 무엇인가요?

 

Q10. 이너클래스의 장점에 대해 설명해주세요.

 

Q11. OOP의 장점과 단점에 대해 설명해주세요.

 

Q12. List, Set, Map의 차이에 대해서 설명해주세요.

 

Q13. 컬렉션과 스트림의 차이에 대해서 설명해주세요.

 

Q14. 제네릭에 대해서 설명하고, 컬렉션 클래스에서 왜 제네릭을 사용하는 지 설명해주세요.

 

 

728x90

기본 타입인 int, long 타입으로 표현할 수 없는 크기의 값을 처리할 때 사용

표현할 수 있는 범위가 크기 때문에 정밀한 작업을 할 때 사용

 

메서드

gcd()

두 값의 최대 공약수를 반환

add()

덧셈

substract()

뺄셈

multiply()

곱셈

divide()

나눗셈

valueOf()

문자열 혹은 숫자를 BigInteger 타입으로 변환

 

비교연산

직접적인 비교연산자 사용은 불가능

equals, compareTo 등을 사용해서 비교

 

변환

Number 클래스를 상속 받기 때문에

int, long, float, double, byte, short로 Value메서드를 사용해 변환 가능

'Java > Notion' 카테고리의 다른 글

JVM 뜯어보기 (컴파일, 인터프리팅, JIT, GC, 메모리)  (0) 2024.03.02
자바의 컴파일 과정  (0) 2023.10.25
Optional<T>  (0) 2023.05.03
Stream  (1) 2023.05.03
Lambda  (0) 2023.05.03
728x90

T 타입 객체의 Wrapper 클래스

null을 포함한 모든 종류의 객체를 저장하기 때문에 null을 간접적으로 다룰 수 있음

NullPorinterException 발생을 예방할 수 있음

null 대신 빈 Optional<T> 객체를 사용하는 것이 좋음

public final class Optional<T> {
	private final T value;
    // null을 포함한 모든 종류의 객체를 저장가능
}

Optional<T> 객체 생성

Optional<String> optVal = Optional.empty(); // 빈 객체로 초기화

Optional<String> optVal - Optional.of(str);
Optional<String> optVal - Optional.of("abc");
Optional<String> optVal - Optional.of(null); // 오류. 불가능
Optional<String> optVal - Optional.ofNullable(null); // 가능

Optional<T> 객체 값 가져오기

String str = optVal.get(); // null이면 예외가 발생하여 잘 사용하지 않음
String str = optVal.orElse(""); // 저장된 값이 null이면 ""반환. 많이 사용
String str = optVal.orElseGet(람다식,메소드참조); // 많이 사용
String str = optVal.or.ElseThrow(NullPointerException::new); // null이면 예외 발생

isPresent() // Optional 객체의 값이 null이면 false, 아니면 true
ifPresent(작업) // null이 아닐 때만 작업 수행, null이면 아무 일도 안함

 

'Java > Notion' 카테고리의 다른 글

자바의 컴파일 과정  (0) 2023.10.25
BigInteger  (0) 2023.05.08
Stream  (1) 2023.05.03
Lambda  (0) 2023.05.03
Thread  (0) 2023.05.02

+ Recent posts