no image
알고리즘 : 병합정렬(Java)
병합정렬 분할정복 알고리즘의 일종!시간복잡도 : O(NlogN)배열을 더이상 나눠지지 않을 때까지 반으로 나눈 후 각각을 정렬하여 병합하는 방식별도의 배열을 생성하여 정렬한 요소들을 담아줘야 함=> 정렬 과정에서 계속 정렬 상태가 유지되는 안정 정렬 방식    정렬 방식 배열을 반으로 나눈다.  (분할)왼쪽 배열의 1번째 인덱스, 오른쪽 배열의 1번째 인덱스부터 비교 (정렬)작은 것을 우선으로 새로운 배열에 옮긴다. (병합)       import java.util.Arrays;public class MergeSort { public static void mergeSort(int[] array, int left, int right) { if (left
2024.09.11
백준: 10158번 개미(자바, Java) 답 정리
[백준] 10158번 개미https://www.acmicpc.net/problem/2164   문제가로 길이가 w이고 세로 길이가 h인 2차원 격자 공간이 있다. 이 격자는 아래 그림처럼 왼쪽 아래가 (0,0)이고 오른쪽 위가 (w,h)이다. 이 공간 안의 좌표 (p,q)에 개미 한 마리가 놓여있다. 개미는 오른쪽 위 45도 방향으로 일정한 속력으로 움직이기 시작한다. 처음에 (p,q)에서 출발한 개미는 1시간 후에는 (p+1,q+1)로 옮겨간다. 단, 이 속력으로 움직이다가 경계면에 부딪치면 같은 속력으로 반사되어 움직인다. 예를 들어 6×4 격자에서 처음에 (4,1)에 있는 개미는 2시간 후에 (6,3)에 있으며 8시간 후에 (0,1)에 있다. 만일 그 개미가 처음에 (5,3)에 있었다면 매 시간마다..
2024.08.15
no image
알고리즘: 병합 정렬 (JAVA)
병합정렬 분할정복 알고리즘의 일종!시간복잡도 : O(NlogN)배열을 더이상 나눠지지 않을 때까지 반으로 나눈 후 각각을 정렬하여 병합하는 방식별도의 배열을 생성하여 정렬한 요소들을 담아줘야 함=> 정렬 과정에서 계속 정렬 상태가 유지되는 안정 정렬 방식    정렬 방식 배열을 반으로 나눈다.  (분할)왼쪽 배열의 1번째 인덱스, 오른쪽 배열의 1번째 인덱스부터 비교 (정렬)작은 것을 우선으로 새로운 배열에 옮긴다. (병합)       import java.util.Arrays;public class MergeSort { public static void mergeSort(int[] array, int left, int right) { if (left
2024.08.12
no image
알고리즘: 버블 정렬 (JAVA)
버블정렬 정렬 방식이 마치 물속 거품이 수면으로 올라가는 듯하다고 하여 붙여진 이름가장 단순하고 이해하기 쉬운 방식 중 하나이다시간복잡도 : O(n^2)    정렬 방식첫 번째 값과 두 번째 값 비교첫 번째 값이 크면 서로 위치 교환. 아니면 그대로!두 번째 값과 세 번째 값 비교하여 같은 작업 반복끝 값까지 같은 작업을 반복하면, 가장 큰 값이 가장 끝 배열 요소로 들어감같은 과정을 반복하면 오름차순 정렬이 완성    장단점장점: 구현이 간단하고 코드가 직관적이다!단점: 시간복잡도가 O(n^2)로, 배열 크기가 커지면 비효율적이다.      import java.util.Arrays;public class BubbleSort { public static void main(String[] args) { ..
2024.08.05
no image
JAVA: 알고리즘, APS, 시간복잡도
알고리즘이란?어떠한 문제를 해결하기 위해 수행해야 하는 절차나 방법을 말한다.  APS(Algorithm Problem Solving)말 그대로 알고리즘 문제를 해결하는 것. 문제 해결능력을 기를 수 있다!    좋은 알고리즘 기준정확도 : 정확한 결과가 출력되는가? 얼마나 정확하게 동작하나? 실행속도(작업량): 적은 연산으로 문제를 해결할 수록 실행속도가 빠르다.메모리 사용량: 적은 메모리를 사용할수록 컴퓨팅 자원을 아낄 수 있다.가독성: 다른 사람이 이해하기 쉽도록 단순해야 한다.최적성: 더 이상 개선의 여지가 없는가?     알고리즘을 나타내는 방식 2가지 의사코드(pseudo code)특정 언어에 관계 없이 쉽게 이해할 수 있도록 나타내는 코드.정해진 규칙이 없이 이해만 잘 되면 됨.   순서도그..
2024.08.04
no image
JAVA : UML 클래스 다이어그램
UML: Unified Modeling Language. 모델을 만들기 위한 표준 언어다른 사람들과 의사소통할 떄 사용시스템의 구조, 클래스 의존성 등 파악건축도면과 같은 느낌크게 2가지 유형(구조 다이어그램, 행위 다이어그램)이고, 유형 별 7개 씩 총 14개의 세부 다이어그램 존재함.클래스 다이어그램은 구조 다이어그램에 속한다!   클래스 다이어그램프로그램의 구조를 그림으로 표현한 것.기본 구성요소는 클래스, 속성, 메서드, 관계인터페이스는 > 추가추상클래스는 >추가 or 이탤릭체로 표기         접근제어자표시범위private-본인 클래스만 접근 가능public+어떤 클래스에서든 접근 가능protected#동일 패키지 or 상속받은 클래스만 접근 가능(default)~동일 패키지만 접근 가능
2024.07.21
no image
JAVA : 상속
상속이란상위 클래스의 속성(=멤버변수)과 메서드(멤버메서드)를 물려 받아 자식 클래스를 정의하는 것상위 클래스가 쓰던 것을 그대로 쓰는데, 거기에 더 확장하고 차별화를 두고 싶을 때 사용상위, 부모, super클래스 자동차 / 개 / 사람      상속의 특징확장성, 재사용성: 자동차 리스트를 관리하는데, 별개로 세단과 전기차, 버스 등을 별도로 관리하고 싶다면?                              자동차의 속성을 그대로 가져가면서도 버스, 수용인원 등의 별도 속성을 관리할 수 있도록                              상속을 활용하여 하위 클래스를 생성할 수 있다.자식 클래스는 부모 클래스의 멤버 변수와 메서드들을 마치 본인이 선언한 것처럼 사용이 가능extends 키워..
2024.07.21
no image
JAVA: JVM 메모리 구조, static, 접근제어자
JVMJava Virtual Mahine - 자바 가상 머신OS에 상관 없이 실행할 수 있도록 만들어주는 역할메서드영역 (method Area) : 클래스, 인터페이스 관련한 정보를 저장하는 영역힙 영역 (heap Area) : 설계도를 통해 만들어진 객체와 그 문자열, 배열 등이 저장되는 영역스택 영역 (stack Area) : 메서드를 호출할 때마다 프레임이 생성되고, 지역변수 등도 함께 임시 저장됨. 해당 메서드가 종료되면 하나씩 사라지는 방식. LIFO 방식(Last In First Out)       static구분staticnon-static 구동 시점클래스가 메서드 영역에 로딩될 때 생성일반 멤버변수이므로, new 키워드 쓸 때(객체 생성할 떄) 만들어짐메모리 할당오직 1개의 메모리 공간 할..
2024.07.18
no image
JAVA: 객체, 클래스, 생성자, 객체지향 프로그래밍(OOP)
객체(국어사전) 의사나 행위가 미치는 대상, 문장 내에서 동사의 행위가 미치는 대상프로그래밍에서는? 데이터와 관련한 알고리즘을 하나의 단위로 묶은 것    객체지향 프로그래밍객체 단위로 묶어 코드를 작성함으로써, 객체 간 상호작용을 활용하는 프로그래밍 방법추상화: 객체의 세부사항을 숨기고 필요한 기능만을 제공함다형성: 상속 관계에서 각 객체가 서로 다른 방식으로 작동하도록 함상속: 기존 클래스를 새로운 클래스가 상속받음으로써 재사용 및 확장이 가능캡슐화: 데이터와 메서드를 하나로 캡슐화함으로써 객체 데이터 등을 숨겨 보안에 강화  >>> 코드의 유지보수, 재사용성, 유연성이 커진다는 장점  클래스객체를 만들기 위한 설계도설계도를 만들어두면, 그 설계도대로 객체들을 만들어낼 수 있다.인스턴스: 클래스를 통..
2024.07.17
자바: Map 클래스, 자주 쓰는 메서드
Map(맵) 인터페이스키-값 쌍을 저장데이터 검색에 효율적이기에 자주 사용키 중복 불가능, 키와 값은 1대1로만 매치     Map(맵) 클래스 데이터 읽기 성능 : HashMap > LinkedHashMap > TreeMap > HashTable종류HashMapTreeMapLinkedHashMapHashTable동기화 여부비동기화비동기화비동기화동기화정렬 순서없음key값에 따라 정렬없음없음삽입 순서 유지없음없음삽입 순서 유지없음null 허용키-값 둘 다 허용값만 허용키-값 둘 다 허용허용 X성능평균 O(1)평균 O(log n)평균 O(1)평균 O(1)      자바에서 큐의 주요 메서드put(K key, V value): 지정된 키와 값을 맵에 추가get(Object key): 지정된 키와 연결된 값을 ..
2024.06.04

알고리즘 : 병합정렬(Java)

친환경 개발자
|2024. 9. 11. 22:27

병합정렬

 

  • 분할정복 알고리즘의 일종!
  • 시간복잡도 : O(NlogN)
  • 배열을 더이상 나눠지지 않을 때까지 반으로 나눈 후 각각을 정렬하여 병합하는 방식
  • 별도의 배열을 생성하여 정렬한 요소들을 담아줘야 함
    => 정렬 과정에서 계속 정렬 상태가 유지되는 안정 정렬 방식

 

 

 

 

정렬 방식

 

  1. 배열을 반으로 나눈다.  (분할)

  2. 왼쪽 배열의 1번째 인덱스, 오른쪽 배열의 1번째 인덱스부터 비교 (정렬)
  3. 작은 것을 우선으로 새로운 배열에 옮긴다. (병합)

 

 

병합정렬 과정

 

 

 

 

 

import java.util.Arrays;

public class MergeSort {
    public static void mergeSort(int[] array, int left, int right) {
        if (left < right) {
            int mid = (left + right) / 2;

            mergeSort(array, left, mid);
            mergeSort(array, mid + 1, right);

            merge(array, left, mid, right);
        }
    }

    private static void merge(int[] array, int left, int mid, int right) {
        int L = mid - left + 1;
        int R = right - mid;

        int[] leftArray = new int[L];
        int[] rightArray = new int[R];

        for (int i = 0; i < L; ++i) {
            leftArray[i] = array[left + i];
        }
        for (int j = 0; j < R; ++j) {
            rightArray[j] = array[mid + 1 + j];
        }

        int i = 0, j = 0;
        int k = left;
        while (i < L && j < R) {
            if (leftArray[i] <= rightArray[j]) {
                array[k] = leftArray[i];
                i++;
            } else {
                array[k] = rightArray[j];
                j++;
            }
            k++;
        }

        while (i < L) {
            array[k] = leftArray[i];
            i++;
            k++;
        }

        while (j < R) {
            array[k] = rightArray[j];
            j++;
            k++;
        }
    }

    public static void main(String[] args) {
        int[] data = {12, 11, 13, 5, 6, 7};
        mergeSort(data, 0, data.length - 1);
        System.out.println(Arrays.toString(data));
    }
}

 


[백준] 10158번 개미

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

 

 

 

문제

가로 길이가 w이고 세로 길이가 h인 2차원 격자 공간이 있다. 이 격자는 아래 그림처럼 왼쪽 아래가 (0,0)이고 오른쪽 위가 (w,h)이다. 이 공간 안의 좌표 (p,q)에 개미 한 마리가 놓여있다. 개미는 오른쪽 위 45도 방향으로 일정한 속력으로 움직이기 시작한다. 처음에 (p,q)에서 출발한 개미는 1시간 후에는 (p+1,q+1)로 옮겨간다. 단, 이 속력으로 움직이다가 경계면에 부딪치면 같은 속력으로 반사되어 움직인다.

 

예를 들어 6×4 격자에서 처음에 (4,1)에 있는 개미는 2시간 후에 (6,3)에 있으며 8시간 후에 (0,1)에 있다. 만일 그 개미가 처음에 (5,3)에 있었다면 매 시간마다 (6,4), (5,3), (4,2), (3,1)로 움직인다. 

여러분은 크기 w×h인 격자 공간에서 처음에 (p,q)에서 출발하는 개미의 t시간 후의 위치 (x,y)를 계산하여 출력해야 한다. 개미는 절대 지치지 않고 같은 속력으로 이동한다고 가정한다. 

문제에서 w와 h는 자연수이며 범위는 2 ≤ w,h ≤ 40,000이다. 그리고 개미의 초기 위치 p와 q도 자연수이며 범위는 각각 0 < p < w과 0 < q < h이다. 그리고 계산할 시간 t의 범위는 1 ≤ t ≤ 200,000,000이다. 

 

입력 :

첫줄에는 w와 h가 공백을 사이에 두고 주어진다. 그 다음 줄에는 초기 위치의 좌표값 p와 q가 공백을 사이에 두고 주어진다. 3번째 줄에는 개미가 움직일 시간 t가 주어진다. 

출력 :

출력은 t 시간 후에 개미의 위치 좌표 (x,y)의 값 x와 y를 공백을 사이에 두고 출력한다. 

 

 

나의 답안

 

 1번째 시도 (실패)

개미가 (p, q) 좌표에서 시작, 초기엔 시간마다 (+1, +1) 씩 이동하다가

 

x한계선에 부딪히면 (-1, +1)이동,  

y한계선에 부딪히면 (+1, -1) 이동,

x, y 한계선에 부딪히면 (-1, -1) 이동하도록 설계했다.


이동할 때마다 이동할 위치를 미리 확인하여 한계선 여부를 확인하고,
확인된 한계선의 좌표 이동값만 -1을 곱하여 바꿔주도록 했다.

 

<1차 시도(실패 코드)>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		// 상하좌우 확인용 배열
//		int[] dr = { -1, 1, 0, 0 };
//		int[] dc = { 0, 0, -1, 1 };
		// 시간당 이동량
		int[] move = { 1, 1 };
		// 개미 현재위치 변수
		int r, c;
		// 개미가 이동할 위치 변수
		int nr, nc;
		// 좌표상으로 개미의 이동 가능 범위가 x : 0 ~ w, y : 0 ~ h 이므로
		// => 배열로는 w+1행 h+1열 지도 생성해야 함
		int w = Integer.parseInt(st.nextToken());
		int h = Integer.parseInt(st.nextToken());

		st = new StringTokenizer(br.readLine());
		// 개미 위치 입력받음
		r = Integer.parseInt(st.nextToken());
		c = Integer.parseInt(st.nextToken());
		// 시간 입력
		int time = Integer.parseInt(br.readLine());

		for (int t = 1; t <= time; t++) {
			// 사방 탐색
			nr = r + move[0];
			nc = c + move[1];
			// nr값이 범위를 넘으면 => 이동량 (-1, 1)
			if (nr < 0 || nr > w) move[0] *= -1;
			// nc값이 범위를 넘으면 => 이동량 (1, -1)
			if (nc < 0 || nc > h) move[1] *= -1;
			// 개미 이동
			r += move[0];
			c += move[1];
		}

		// time시간 후 개미 위치 출력
		System.out.println(r + " " + c);
	}
}

 

 

 

2번째 시도 (성공)

 

1차 시도에서 시간 초과 발생. time이 최대 2억이므로 for문을 사용하면 안될 것이라고 판단했다.

 

  1.  time을 최대 좌표값으로 나눴을 때 

    몫이 짝수이면 => 2바퀴 돌고 제자리로 돌아오고, 이동량은 그대로 +1

    몫이 홀수이면 => 1바퀴 돌아 원래 자리의 대칭점으로 이동. 이동량은 반대인 -1

  2. time을 좌표값으로 나눈 나머지만큼 이동해주면 최종 위치값이 된다.

<2차 코드(성공)>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class S3_10158_개미 {

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		// 개미 현재위치 변수
		int r, c;
        
		st = new StringTokenizer(br.readLine());
        
		// 개미 위치 입력받음
		r = Integer.parseInt(st.nextToken());
		c = Integer.parseInt(st.nextToken());
        
		// 시간 입력
		int time = Integer.parseInt(br.readLine());
        
		// 몫이 짝수이면 다시 제자리로 돌아온 것과 같음
		if (time / w % 2 == 0) {
			// 제자리에서 (+1 * 나머지) 만큼 이동
			r = r + (time % w) > w ? w - (r + (time % w) - w) : r + (time % w);
		// 몫이 홀수이면 원래 자리의 대칭점으로 이동한 것과 같음
		} else {
			// 대칭점에서 (-1 * 나머지) 만큼 이동
			r = r + (time % w - w) < 0 ? - (r + (time % w - w)) : r + (time % w - w);
		}
        
		// y좌표도 동일하게 이동 처리
		if (time / h % 2 == 0) {
			c = c + (time % h) > h ? h - (c + (time % h) - h) : c + (time % h);
		} else {
			c = c + (time % h - h) < 0 ? - (c + (time % h - h)) : c + (time % h - h);
		}
        
		System.out.println(r + " " + c);
	}
}

 

개선 사항

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        String[] size = br.readLine().split(" ");
        int w = Integer.parseInt(size[0]);
        int h = Integer.parseInt(size[1]);
        
        String[] point = br.readLine().split(" ");
        int p = Integer.parseInt(point[0]);
        int q = Integer.parseInt(point[1]);
        
        int t = Integer.parseInt(br.readLine());
        
        int x = (t + p) % (2 * w);
        int y = (t + q) % (2 * h);
        
        if (x > w) {
            x = 2 * w - x;
        }
        
        if (y > h) {
            y = 2 * h - y;
        }
        
        System.out.println(x + " " + y);
    }
    
}
  • x, y좌표의 계산을 매우 간결하게 처리했다.
  • x, y좌표가 범위를 넘었을 경우를 별도 if문으로 처리하여 가독성이 좋아졌다.

 

문제에 좌표가 있으면 일단 무조건 배열을 생성하고

 

시간별로 일일이 처리하도록 계산했었는데,

 

이렇게 간단한 계산식으로 처리할 수가 있다는 것을

 

바로 생각해내지 못했다.

 

항상 정해진 답은 없다는 것을 생각하고

 

더 효율적인 방법이 있을지 생각해봐야 하겠다.

알고리즘: 병합 정렬 (JAVA)

친환경 개발자
|2024. 8. 12. 23:45

병합정렬

 

  • 분할정복 알고리즘의 일종!
  • 시간복잡도 : O(NlogN)
  • 배열을 더이상 나눠지지 않을 때까지 반으로 나눈 후 각각을 정렬하여 병합하는 방식
  • 별도의 배열을 생성하여 정렬한 요소들을 담아줘야 함
    => 정렬 과정에서 계속 정렬 상태가 유지되는 안정 정렬 방식

 

 

 

 

정렬 방식

 

  1. 배열을 반으로 나눈다.  (분할)

  2. 왼쪽 배열의 1번째 인덱스, 오른쪽 배열의 1번째 인덱스부터 비교 (정렬)
  3. 작은 것을 우선으로 새로운 배열에 옮긴다. (병합)

 

 

병합정렬 과정

 

 

 

 

 

import java.util.Arrays;

public class MergeSort {
    public static void mergeSort(int[] array, int left, int right) {
        if (left < right) {
            int mid = (left + right) / 2;

            mergeSort(array, left, mid);
            mergeSort(array, mid + 1, right);

            merge(array, left, mid, right);
        }
    }

    private static void merge(int[] array, int left, int mid, int right) {
        int L = mid - left + 1;
        int R = right - mid;

        int[] leftArray = new int[L];
        int[] rightArray = new int[R];

        for (int i = 0; i < L; ++i) {
            leftArray[i] = array[left + i];
        }
        for (int j = 0; j < R; ++j) {
            rightArray[j] = array[mid + 1 + j];
        }

        int i = 0, j = 0;
        int k = left;
        while (i < L && j < R) {
            if (leftArray[i] <= rightArray[j]) {
                array[k] = leftArray[i];
                i++;
            } else {
                array[k] = rightArray[j];
                j++;
            }
            k++;
        }

        while (i < L) {
            array[k] = leftArray[i];
            i++;
            k++;
        }

        while (j < R) {
            array[k] = rightArray[j];
            j++;
            k++;
        }
    }

    public static void main(String[] args) {
        int[] data = {12, 11, 13, 5, 6, 7};
        mergeSort(data, 0, data.length - 1);
        System.out.println(Arrays.toString(data));
    }
}

 

알고리즘: 버블 정렬 (JAVA)

친환경 개발자
|2024. 8. 5. 16:21

버블정렬

 

  • 정렬 방식이 마치 물속 거품이 수면으로 올라가는 듯하다고 하여 붙여진 이름
  • 가장 단순하고 이해하기 쉬운 방식 중 하나이다
  • 시간복잡도 : O(n^2)

 

 

 

 

정렬 방식

  1. 첫 번째 값과 두 번째 값 비교
  2. 첫 번째 값이 크면 서로 위치 교환. 아니면 그대로!
  3. 두 번째 값과 세 번째 값 비교하여 같은 작업 반복
  4. 끝 값까지 같은 작업을 반복하면, 가장 큰 값이 가장 끝 배열 요소로 들어감
  5. 같은 과정을 반복하면 오름차순 정렬이 완성

 

 

 

 

장단점

  • 장점: 구현이 간단하고 코드가 직관적이다!
  • 단점: 시간복잡도가 O(n^2)로, 배열 크기가 커지면 비효율적이다.

 

 

 

 

 

 

import java.util.Arrays;

public class BubbleSort {

	public static void main(String[] args) {
		int[] arr = {22, 42, 31, 10, 35};
		
		// 버블 정렬
		for (int i=0; i<arr.length; i++) {
			for (int j=1; j<arr.length-i; j++) {
				if (arr[j-1] > arr[j]) {
					int tmp = arr[j-1];
					arr[j-1] = arr[j];
					arr[j] = tmp;
				}
			}
		}
		
		System.out.println(Arrays.toString(arr));
	}

}

 

JAVA: 알고리즘, APS, 시간복잡도

친환경 개발자
|2024. 8. 4. 13:30

알고리즘이란?

어떠한 문제를 해결하기 위해 수행해야 하는 절차나 방법을 말한다.

 

 

APS(Algorithm Problem Solving)

말 그대로 알고리즘 문제를 해결하는 것. 

문제 해결능력을 기를 수 있다!

 

 

 

 

좋은 알고리즘 기준

  1. 정확도 : 정확한 결과가 출력되는가? 얼마나 정확하게 동작하나? 
  2. 실행속도(작업량): 적은 연산으로 문제를 해결할 수록 실행속도가 빠르다.
  3. 메모리 사용량: 적은 메모리를 사용할수록 컴퓨팅 자원을 아낄 수 있다.
  4. 가독성: 다른 사람이 이해하기 쉽도록 단순해야 한다.
  5. 최적성: 더 이상 개선의 여지가 없는가?

 

 

 

 

 

알고리즘을 나타내는 방식 2가지

 

  • 의사코드(pseudo code)

특정 언어에 관계 없이 쉽게 이해할 수 있도록 나타내는 코드.

정해진 규칙이 없이 이해만 잘 되면 됨.

 

 

 

  • 순서도

그림으로 표현한 방식으로, 조건문(분기문)은 마름모꼴로 표현한다.

 

 

시간복잡도(Time Complexity)

알고리즘의 작업량 및 효율성을 계산할 때, Big-O 표기법을 가장 많이 사용.

실제 걸리는 시간을 측정하거나 연산의 수를 계산하는 것은 현실적으로 어렵기 때문에

가장 큰 영향력을 주는 n에 대한 항만을 표시하여 사용!!

  • 계수는 생략한다
  • 최악의 경우를 가정하여 계산하는 방식

 

 

알고리즘 문제풀이 5단계

  1. 문제를 꼼꼼하게 읽고 데이터 범위, 조건을 확인한다
  2. 조건과 데이터의 범위에 맞는 자료형 선정, 알고리즘을 선택한다.
  3. 문제풀이 방식을 구상한다
  4. 구상한 방식을 코드로 작성한다
  5. 알맞게 답이 출력되는지 확인하고 수정한다.

JAVA : UML 클래스 다이어그램

친환경 개발자
|2024. 7. 21. 23:32

UML

: Unified Modeling Language. 모델을 만들기 위한 표준 언어

  • 다른 사람들과 의사소통할 떄 사용
  • 시스템의 구조, 클래스 의존성 등 파악
  • 건축도면과 같은 느낌
  • 크게 2가지 유형(구조 다이어그램, 행위 다이어그램)이고, 유형 별 7개 씩 총 14개의 세부 다이어그램 존재함.
  • 클래스 다이어그램은 구조 다이어그램에 속한다!

 

 

 

클래스 다이어그램

  • 프로그램의 구조를 그림으로 표현한 것.
  • 기본 구성요소는 클래스, 속성, 메서드, 관계
  • 인터페이스는 <<interface>> 추가
  • 추상클래스는 <<abstract>>추가 or 이탤릭체로 표기

 

 

 

 

 

 

 

 

 

접근제어자 표시 범위
private - 본인 클래스만 접근 가능
public + 어떤 클래스에서든 접근 가능
protected # 동일 패키지 or 상속받은 클래스만 접근 가능
(default) ~ 동일 패키지만 접근 가능

 

 

 

 

 

JAVA : 상속

친환경 개발자
|2024. 7. 21. 14:00

상속이란

  • 상위 클래스의 속성(=멤버변수)과 메서드(멤버메서드)를 물려 받아 자식 클래스를 정의하는 것
  • 상위 클래스가 쓰던 것을 그대로 쓰는데, 거기에 더 확장하고 차별화를 두고 싶을 때 사용
  • 상위, 부모, super클래스 <---- 하위, 자식, sub 클래스
    자동차 / 개 / 사람 <---- 세단, 트럭,... / 말티즈, 요크셔테리어,... / 요리사, 학생,...

 

 

 

 

 

상속의 특징

  • 확장성, 재사용성: 자동차 리스트를 관리하는데, 별개로 세단과 전기차, 버스 등을 별도로 관리하고 싶다면?
                                  자동차의 속성을 그대로 가져가면서도 버스, 수용인원 등의 별도 속성을 관리할 수 있도록
                                  상속을 활용하여 하위 클래스를 생성할 수 있다.
  • 자식 클래스는 부모 클래스의 멤버 변수와 메서드들을 마치 본인이 선언한 것처럼 사용이 가능
  • extends 키워드를 사용해 상속받을 수 있다 :
              [접근제어자] (static) 클래스명 extends 부모클래스명 {

              }
  • 생성자 호출 시 super() 키워드 사용! (생략해도 구동 시 알아서 부모 클래스에서 찾아온다.)
  • super키워드는 반드시 자식클래스 생성자 내 첫 번째 줄에 위치해야만 한다!
class Car {    // 부모 클래스
    String brand;
    int year;

    // 기본 생성자
    Car() {
        this.brand = "Unknown";
        this.year = 0;
        System.out.println("Car의 기본 생성자가 호출되었습니다.");
    }

    // 파라미터를 입력받는 생성자
    Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
        System.out.println("Car의 파라미터 생성자가 호출되었습니다.");
    }
}

 

class Sedan extends Car {    //자식 클래스
    int seats;

    // 기본 생성자
    Sedan() {
        // super()는 부모 클래스의 기본 생성자를 호출합니다.
       super();
        this.seats = 5;
        System.out.println("Sedan의 기본 생성자가 호출되었습니다.");
    }

    // 파라미터를 입력받는 생성자
    Sedan(String brand, int year, int seats) {
        // super(brand, year)는 부모 클래스의 파라미터를 입력받는 생성자를 호출합니다.
        super(brand, year);
        this.seats = seats;
        System.out.println("Sedan의 파라미터 생성자가 호출되었습니다.");
    }
}

 

 

Object 클래스??

  • 모든 클래스는 Object라는 클래스를 기본적으로 상속받고 있다. extends Object를 쓰지 않아도 알아서 상속한다.
  • equals(), hashCode(), toString() 등의 메서드를 선언하지 않고 사용하는 것은 Object클래스에 이미 마련되었기 때문!

 

 

 

오버라이딩

  • 상위 클래스에서 선언된 메서드를 상속받은 자식 클래스에서 재정의하는 것 ( = 덮어쓰기)
  • 서드의 이름, 반환형, 매개변수가 모두 동일해야 한다! = 단지 메서드 내부 로직이 바뀌는 것!
  • 반드시 상속 관계에서만 사용 가능
  • 어노테이션 표시를 해야 한다. (권장)
  • 조상보다 더 큰 예외를 던질 수 없다.

 

class Car {
    void startEngine() {
        System.out.println("엔진이 켜졌습니다.");
    }
}

class ElectricCar extends Car {
    // 오버라이딩: ElectricCar만의 방식으로 startEngine 메서드를 다시 정의합니다.
    @Override    // 어노테이션
    void startEngine() {
        System.out.println("전기 엔진이 조용히 켜졌습니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        ElectricCar myElectricCar = new ElectricCar();
        myElectricCar.startEngine();  // "전기 엔진이 조용히 켜졌습니다." 출력
    }
}

JVM

  • Java Virtual Mahine - 자바 가상 머신
  • OS에 상관 없이 실행할 수 있도록 만들어주는 역할
  • 메서드영역 (method Area) : 클래스, 인터페이스 관련한 정보를 저장하는 영역
  • 힙 영역 (heap Area) : 설계도를 통해 만들어진 객체와 그 문자열, 배열 등이 저장되는 영역
  • 스택 영역 (stack Area) : 메서드를 호출할 때마다 프레임이 생성되고, 지역변수 등도 함께 임시 저장됨. 해당 메서드가 종료되면 하나씩 사라지는 방식. LIFO 방식(Last In First Out)

 

 

 

 

 

 

 

static

구분 static non-static
 구동 시점 클래스가 메서드 영역에 로딩될 때 생성 일반 멤버변수이므로, new 키워드 쓸 때(객체 생성할 떄) 만들어짐
메모리 할당 오직 1개의 메모리 공간 할당 인스턴스마다 별도로 할당
목적 모든 인스턴스에 공용으로 사용할 변수 or 메서드를 정의할 떄 주로 사용 개별적으로 관리할 때 사용
접근 방법 클래스 이름으로 접근
Dog.age = 2;
객체를 생성해야 접근 가능
Dog dog = new Dog();
dog.age = 2;

 

 

 

 

★ static영역에서는 non-static 영역에 직접 접근이 불가하고

 

     non-static 영역에서는 static 영역에 접근이 가능하다!

 

staitc 영역인 main 메서드에서 선언된 name은 

 

non-static 영역인 '스태틱'클래스에서 접근이 가능.

 

그러나 반대로 age는 메인 메서드 영역에서 접근이 불가능하다!

 

 

 

 

 

접근제어자

  • private : 자기 클래스에서만 접근 가능
  • protected : 같은 패키지(폴더) 에서 접근 가능, 다른 패키지에서는 접근 안됨.
                      But 다른 패키지 클래스를 상속받았다면? 상속받은 본인 클래스로 선언하면 가능
  • (default) : 제어자 입력이 없다면 default로 적용됨. 같은 패키지 에서만 접근 가능
  • public : 모든 위치에서 접근 가능

  동일 클래스(자기 자신) 동일 패키지 다른 패키지의 하위 클래스 다른 패키지
private 접근가능 접근 불가능 접근 불가능 접근 불가능
default 접근가능 접근가능 접근 불가능 접근 불가능
protected 접근가능 접근가능 접근가능 접근 불가능
public 접근가능 접근가능 접근가능 접근가능

객체


(국어사전) 의사나 행위가 미치는 대상, 문장 내에서 동사의 행위가 미치는 대상

프로그래밍에서는? 데이터와 관련한 알고리즘을 하나의 단위로 묶은 것

 

 

 

 

객체지향 프로그래밍


객체 단위로 묶어 코드를 작성함으로써, 객체 간 상호작용을 활용하는 프로그래밍 방법

  • 추상화: 객체의 세부사항을 숨기고 필요한 기능만을 제공함
  • 다형성: 상속 관계에서 각 객체가 서로 다른 방식으로 작동하도록 함
  • 상속: 기존 클래스를 새로운 클래스가 상속받음으로써 재사용 및 확장이 가능
  • 캡슐화: 데이터와 메서드를 하나로 캡슐화함으로써 객체 데이터 등을 숨겨 보안에 강화

  >>> 코드의 유지보수, 재사용성, 유연성이 커진다는 장점

 

 

클래스


  • 객체를 만들기 위한 설계도
  • 설계도를 만들어두면, 그 설계도대로 객체들을 만들어낼 수 있다.
  • 인스턴스: 클래스를 통해 만들어진 해당 객체 >> 실제 메모리에 생성
  • 멤버변수: 속성(데이터)
  • 멤버메서드: 동작(메서드)
  • 생성자: 객체를 생성할 때 호출하는 특별한 메서드
  • 기본생성자: 클래스 작성 시 별도로 사용자가 작성하지 않으면 자동으로 JVM에서 생성함.
                        별도 작성 있으면 기본생성자 호출 불가!

 

 

 

생성자


  • new키워드와 함께 호출
  • 클래스명과 동일해야한다
  • 반환타입 없다(void조차 없음)
  • 객체 생성 시 반드시 생성자가 호출된다(new로 생성 시)
  • 객체의 멤버 필드를 선언과 동시에 초기화할 때 주로 사용한다
  • 웬만하면 기본 생성자를 직접 만들어주는 것이 좋다!
  • this : 생성된 인스턴스가 가지고 있는, 참조하는 값

 

public class Movie {

//멤버변수
int id;
String title;
String director;
String genre;
int runningTime;

//기본생성자
Movie() {
System.out.println("기본생성자 호출");
}

//매개변수 받는 생성자
Movie(int id, String title, String director, String genre, int runningTime) {
this.id = id;
this.title = title;
this.director = director;
this.genre = genre;
this.runningTime = runningTime;
}

//메서드
void movieInfo() {
System.out.printf("등록번호: %d\n제목: %s\n제작자: %s\n장르: %s\n상영시간: %d", id, title, director, genre, runningTime);
}
    
}

 

 

public class MovieTest {

public static void main(String[] args) {

//객체 생성
Movie movie1 = new Movie(1, "인터스텔라", "놀란", "스릴러", 300);
Movie movie2 = new Movie(2, "마더", "봉준호", "공포", 100);
Movie movie3 = new Movie(3, "아바타", "카메룬", "판타지", 92);

movie1.movieInfo();
System.out.println("\n");
movie2.movieInfo();
System.out.println("\n");
movie3.movieInfo();
System.out.println("\n");
 
}

}

자바: Map 클래스, 자주 쓰는 메서드

친환경 개발자
|2024. 6. 4. 21:25



Map(맵) 인터페이스

  • 키-값 쌍을 저장
  • 데이터 검색에 효율적이기에 자주 사용
  • 키 중복 불가능, 키와 값은 1대1로만 매치

 

 

 

 

 

Map(맵) 클래스

 

데이터 읽기 성능 : HashMap > LinkedHashMap > TreeMap > HashTable

종류 HashMap TreeMap LinkedHashMap HashTable
동기화 여부 비동기화 비동기화 비동기화 동기화
정렬 순서 없음 key값에 따라 정렬 없음 없음
삽입 순서 유지 없음 없음 삽입 순서 유지 없음
null 허용 키-값 둘 다 허용 값만 허용 키-값 둘 다 허용 허용 X
성능 평균 O(1) 평균 O(log n) 평균 O(1) 평균 O(1)

 

 

 

 

 

 

자바에서 큐의 주요 메서드

  • put(K key, V value): 지정된 키와 값을 맵에 추가
  • get(Object key): 지정된 키와 연결된 값을 반환
  • containsKey(Object key): 맵에 지정된 키가 포함되어 있는지 확인
  • containsValue(Object value): 맵에 지정된 값이 포함되어 있는지 확인
  • remove(Object key): 지정된 키로 맵에서 요소를 제거
  • size(): 맵에 있는 키-값 쌍의 수를 반환
  • keySet(): 맵의 모든 키를 포함하는 Set을 반환
  • values(): 맵의 모든 값을 포함하는 Collection을 반환
  • entrySet(): 맵의 모든 키-값 쌍을 포함하는 Set을 반환
  • isEmpty(): 맵이 비어 있는지 확인
  • clear(): 맵의 모든 요소를 제거

 

 

 

 

 

예시

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        
        // put: 요소 추가
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);
        
        // get: 키로 값 가져오기
        System.out.println("Apple: " + map.get("Apple"));
        
        // containsKey: 키가 존재하는지 확인
        System.out.println("Contains 'Banana': " + map.containsKey("Banana"));
        
        // containsValue: 값이 존재하는지 확인
        System.out.println("Contains value 3: " + map.containsValue(3));
        
        // remove: 키로 요소 제거
        map.remove("Cherry");
        
        // size: Map의 크기
        System.out.println("Map size: " + map.size());
        
        // keySet: 모든 키를 Set으로 반환
        System.out.println("Keys: " + map.keySet());
        
        // values: 모든 값을 Collection으로 반환
        System.out.println("Values: " + map.values());
        
        // entrySet: 모든 키-값 쌍을 Set으로 반환
        System.out.println("Entries: " + map.entrySet());
        
        // isEmpty: Map이 비어 있는지 확인
        System.out.println("Is map empty: " + map.isEmpty());
        
        // clear: 모든 요소 제거
        map.clear();
        System.out.println("Is map empty after clear: " + map.isEmpty());
    }
}