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


문제

두 자연수 A와 B가 있을 때, A%B는 A를 B로 나눈 나머지 이다. 예를 들어, 7, 14, 27, 38을 3으로 나눈 나머지는 1, 2, 0, 2이다. 

수 10개를 입력받은 뒤, 이를 42로 나눈 나머지를 구한다. 그 다음 서로 다른 값이 몇 개 있는지 출력하는 프로그램을 작성하시오.

입력

첫째 줄부터 열번째 줄 까지 숫자가 한 줄에 하나씩 주어진다. 이 숫자는 1,000보다 작거나 같고, 음이 아닌 정수이다.

출력

첫째 줄에, 42로 나누었을 때, 서로 다른 나머지가 몇 개 있는지 출력한다.


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

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());

		boolean[] arr = new boolean[42];
		int answer = 0;
		int count = 0;

		for (int i = 0; i < 10; i++) {
			arr[Integer.parseInt(br.readLine()) % 42] = true;
		}

		for (int i = 0; i < 42; i++) {
			if (arr[i]) {
				count++;
			}
		}
		System.out.println(count);
	}
}

제수가 42로 고정이기 때문에 42바이트 boolean 형식의 배열을 선언하여

각 나머지를 해당 자리수 배열에 저장한뒤 true 개수를 출력

 

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

public class Main {

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//		StringTokenizer st = new StringTokenizer(br.readLine());

		HashSet<Integer> hs = new HashSet<Integer>();

		for (int i = 0; i < 10; i++) 
			hs.add(Integer.parseInt(br.readLine()) % 42);

		System.out.println(hs.size());

	}
}

Hashset 로도 가능

| JAVA Collection Framework의 상속 기본 구조

 

List, Map, Set에 관해 설명드리기 전에 컬렉션 프레임워크를 사용하는 이유에 대해 말씀드리자면, 기존에는 많은 데이터를 처리하기 위해 배열을 사용했었지만 크기가 고정되어있고 삽입 및 삭제 시간이 오래 걸린다는 불편한 점들이 많았습니다. 따라서 이를 보완하기 위해 자바에서 동적 배열 개념인 컬렉션 프레임워크를 제공하였는데 종류는 대표적으로 List, Map, Set이 있습니다. 그리하여 자바 컬렉션 프레임워크로 인해 자료의 삽입, 삭제, 검색 등등이 용이해지고 어떠한 자료형이라도 담을 수 있으며 크기가 자유롭게 늘어난다는 강점을 가져 많은 사람들에게 사용되고 있습니다.

 


| List

 

순서가 있고 중복을 허용합니다.
인덱스로 원소에 접근이 가능합니다.
크기가 가변적입니다.

List의 종류와 특징

  • LinkedList
    • 양방향 포인터 구조로 데이터 삽입, 삭제가 빠르다.
    • ArrayList보다 검색이 느리다. 
  • ArrayList
    • 단반향 포인터 구조로 데이터 순차적 접근에 강점을 가진다.
    • 배열을 기반으로 데이터를 저장한다.
    • 데이터 삽입, 삭제가 느리다.
    • 데이터 검색이 빠르다.

| Map

 

Key와 Value의 한쌍으로 이루어지는 데이터의 집합.
Key에 대한 중복이 없으며 순서를 보장하지 않습니다.
뛰어난 검색 속도를 가집니다.
인덱스가 따로 존재하지 않기 때문에 iterator를 사용합니다.

Map의 종류와 특징

  • HashMap
    • Key에 대한 중복이 없으며 순서를 보장하지 않는다.
    • Key와 Value 값으로 NULL을 허용한다.
    • 동기화가 보장되지 않는다.
    • 검색에 가장 뛰어난 성능을 가진다.
  • HashTable
    • 동기화가 보장되어 병렬 프로그래밍이 가능하고 HashMap 보다 처리속도가 느리다.
    • Key와 Value 값으로 NULL을 허용하지 않는다.
  • LinkedHashMap
    • 입력된 순서를 보장한다.
  • TreeMap
    • 이진 탐색 트리(Red-Black Tree)를 기반으로 키와 값을 저장한다.
    • Key 값을 기준으로 오름차순 정렬되고 빠른 검색이 가능하다.
    • 저장 시 정렬을 하기 때문에 시간이 다소 오래 걸린다.

| Set

 

데이터의 집합이며 순서가 없고 중복된 데이터를 허용하지 않습니다.
중복되지 않은 데이터를 구할 때 유용합니다.
빠른 검색 속도를 가집니다.
인덱스가 따로 존재하지 않기 때문에 iterator를 사용합니다.

Set의 종류와 특징

  • HashSet
    • 인스턴스의 해시값을 기준으로 저장하기 때문에 순서를 보장하지 않는다.
    • NULL 값을 허용한다.
    • TreeSet보다 삽입, 삭제가 빠르다.
  • LinkedHashSet
    • 입력된 순서를 보장한다.
  • TreeSet
    • 이진 탐색 트리(Red-Black Tree)를 기반으로 한다.
    • 데이터들이 오름차순으로 정렬된다.
    • 데이터 삽입, 삭제에는 시간이 걸리지만 검색, 정렬이 빠르다.

 

 

| 정리

 

List는 기본적으로 데이터들이 순서대로 저장되며 중복을 허용한다.

Map은 순서가 보장되지 않고 Key값의 중복은 허용하지 않지만 Value값의 중복은 허용된다.

Set은 순서가 보장되지 않고 데이터들의 중복을 허용하지 않는다.

 

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

 

2562번: 최댓값

9개의 서로 다른 자연수가 주어질 때, 이들 중 최댓값을 찾고 그 최댓값이 몇 번째 수인지를 구하는 프로그램을 작성하시오. 예를 들어, 서로 다른 9개의 자연수 3, 29, 38, 12, 57, 74, 40, 85, 61 이 주어

www.acmicpc.net


문제

9개의 서로 다른 자연수가 주어질 때, 이들 중 최댓값을 찾고 그 최댓값이 몇 번째 수인지를 구하는 프로그램을 작성하시오.

예를 들어, 서로 다른 9개의 자연수

3, 29, 38, 12, 57, 74, 40, 85, 61

이 주어지면, 이들 중 최댓값은 85이고, 이 값은 8번째 수이다.

입력

첫째 줄부터 아홉 번째 줄까지 한 줄에 하나의 자연수가 주어진다. 주어지는 자연수는 100 보다 작다.

출력

첫째 줄에 최댓값을 출력하고, 둘째 줄에 최댓값이 몇 번째 수인지를 출력한다.


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

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[] arr = new int[9];
		int max = 0;
		int index = 0;
		int N;
		
		for (int i = 0; i < 9; i++) {
			N = Integer.parseInt(br.readLine());
			if (max < N) {
				max = N;
				index = i+1;
			}
		}

		System.out.println(max);
		System.out.println(index);
	}

}

최댓값을 구하는 단순한 문제

배열에 입력값을 저장한 뒤 max 변수랑 비교했을 때 더 큰 값이 나올때마다 max에 저장 해주고

index 값을 따로 저장해주면 되는 단순한 문제다

위와 같이 class명이 Main이 아닐경우

class 클래스명 is public, should be declared in a file named 클래스명.java 라는 컴파일 에러가 호출된다.

class명을 Main으로 변경만 해주면 해결끝!

흔한 수학 문제 중 하나는 주어진 점이 어느 사분면에 속하는지 알아내는 것이다. 사분면은 아래 그림처럼 1부터 4까지 번호를 갖는다. "Quadrant n"은 "제n사분면"이라는 뜻이다.

예를 들어, 좌표가 (12, 5)인 점 A는 x좌표와 y좌표가 모두 양수이므로 제1사분면에 속한다. 점 B는 x좌표가 음수이고 y좌표가 양수이므로 제2사분면에 속한다.

점의 좌표를 입력받아 그 점이 어느 사분면에 속하는지 알아내는 프로그램을 작성하시오. 단, x좌표와 y좌표는 모두 양수나 음수라고 가정한다.

입력

첫 줄에는 정수 x가 주어진다. (−1000 ≤ x ≤ 1000; x ≠ 0) 다음 줄에는 정수 y가 주어진다. (−1000 ≤ y ≤ 1000; y ≠ 0)

출력

점 (x, y)의 사분면 번호(1, 2, 3, 4 중 하나)를 출력한다.


단순한 if문 문제다.

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

public class Main {
	static int N, M;

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

		int result = 0;
		N = Integer.parseInt(br.readLine());
		M = Integer.parseInt(br.readLine());

		if (N > 0 && M > 0)
			result = 1;
		else if (N <0 && M > 0)
			result = 2;
		else if (N < 0 && M < 0)
			result = 3;
		else if (N > 0 && M < 0)
			result = 4;

		System.out.println(result);
	}
}

www.acmicpc.net/problem/2588

 

2588번: 곱셈

첫째 줄부터 넷째 줄까지 차례대로 (3), (4), (5), (6)에 들어갈 값을 출력한다.

www.acmicpc.net

문제

(세 자리 수) × (세 자리 수)는 다음과 같은 과정을 통하여 이루어진다.

(1)과 (2)위치에 들어갈 세 자리 자연수가 주어질 때 (3), (4), (5), (6)위치에 들어갈 값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 (1)의 위치에 들어갈 세 자리 자연수가, 둘째 줄에 (2)의 위치에 들어갈 세자리 자연수가 주어진다.

출력

첫째 줄부터 넷째 줄까지 차례대로 (3), (4), (5), (6)에 들어갈 값을 출력한다.


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

public class Main {
	static int N, M;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int out1, out2, out3, res;

		N = Integer.parseInt(br.readLine());
		M = Integer.parseInt(br.readLine());

		out1 = N * ((M % 100) % 10);
		out2 = N * ((M % 100) / 10);
		out3 = N * (M / 100);
		res = N * M;

		System.out.println(out1);
		System.out.println(out2);
		System.out.println(out3);
		System.out.println(res);
	}
}

 

| StringTokenizer 사용법

StringTokenizer는 긴 문자열을 지정된 구분자를 기준으로 문자열을 슬라이싱하는데 사용된다.
100,200,300,400의 문자열을 , 구분자를 기준으로 슬라이싱하게 되면 4개의 문자열을 획득할 수 있다.
StringTokenizer의 경우 단 한개의 구분자를 사용해야 한다는 단점이 있으므로 복잡한 형태의 구분자로 문자열을 나누어야 할 때는  Scanner나 split를 사용해야 한다.

StringTokenizer 생성자 및 메소드는 다음 표와 같다.

생성자/메소드 설  명
StringTokenizer(String str, String delim) 문자열을 지정된 구분자로 나누는 StringTokenizer를 생성한다.
구분자는 토큰으로 간주되지 않음
StringTokenizer(String str, String delim, boolean returnDelims) 구분자도 토큰으로 간주
int countTokens() 전체 토큰의 수를 반환
boolean hasMoreTokens() 토큰이 남아있는지 알려 줌
String nextToken() 다음 토큰을 반환

| 소스코드

import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) {
		String source = "100,200,300,400";
		StringTokenizer st = new StringTokenizer(source, ",");
		while (st.hasMoreTokens()) {
			System.out.println(st.nextToken());
		}
	}

}

결과값

100
200
300
400

| Scanner 와 BufferedReader의 차이

이번 글은 자바를 처음 배울때 한번쯤은 써봤을 법한 클래스인 Scanner와 프로그래밍에 조금 더 익숙해지거나 특히 알고리즘 문제를 풀다가 자주 접하게 될 BufferedReader 클래스의 차이에 대해 알아보겠습니다.

결론부터 말하자면 가장 큰 차이점은 속도!!

 

package milk;

import java.util.Scanner;

public class study {

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

		System.out.println("원하는 숫자를 입력하세요");
		String input = scanner.nextLine();
		int num = Integer.parseInt(input);

		System.out.println(num);
	}

}

 

우리는 보통 자바를 처음 배울때 콘솔에서 입력을 받기 위해 이러한 방식을 많이 사용했을 것이다. 하지만 Scanner는 편리하지만 속도가 느리다는 단점이 있어 특히 알고리즘 문제를 풀때 시간초과 에러를 내는 치명적인 단점이 있습니다. 하하지만  BufferedReader 를 아래와 같이 사용한다면 버퍼를 사용하기 때문에 입력 속도에서 확연히 줄일 수 있습니다.

package milk;

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

public class study {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 선언
		String s = br.readLine(); 
		int i = Integer.parseInt(br.readLine()); 
		
		System.out.println("String : " + s);
		System.out.println("Int : " + i);
		
	}
}

 

 

 

각 언어마다 입력방식에 대한 속도가 차이가 조금씩 있습니다. 알고리즘 사이트에서 보면 C/C++이 JAVA 보다 실행속도가 빠른 이유가 여기에 있습니다.

입력방식에 따른 속도 차이






개발자라면 한번쯤 사용해 봤을 이클립스, 쓰다보면 기본 클래식 테마에 지루함을 느껴본 적이 있을 것 같아요.          오랜시간 보는 화면인 만큼 환경이 중요하겠죠..! 저도 하얀 화면을 오래보고 눈이 아프다보니 검은 화면을 더 선호하게 되었습니다.

그럼 어두운 화면으로 바꾸어 보겠습니다.

 

1. 메뉴바에 있는 [Window] - [Preferences]를 클릭합니다.

 

2. [General] - [Appearance] - [Theme]를 보면 원하는 취향에 맞게 선택할 수 있는 테마 종류들이 나타납니다.

원하는 테마 선택후 [Apply and Cloase] 클릭!

 

3. 기존 하얀 배경이었던 테마가 검정으로 바뀌었습니다.

 

이클립스에서 기본으로 제공되는 것 외 다른 테마도 사용하는 법!

 

1. [Help] - [Eclipse Marketplace...] 클릭

 

2. theme 를 검색하면 [Darkest Dark Theme with DevStyle CI] 라는 이름의 테마 [install] 클릭!

 

 

3. [confirm] 클릭

4. [Finish] 완료버튼 클릭!

 

5. 아래 빨간 네모 install 문구를 더블클릭하면 진행상황을 볼 수 있습니다.

 

6. [RESTART NOW] 클릭

 

7. 아까와는 다른 스타일의 어두운 테마로 변경 완료!

자바 프로그램 실행과정

- Java언어로 프로그래밍된 파일을 Java컴파일러가 가상 기계어 파일인 Java클래스 파일로 만든다. 다시 말해, 소스 코드를 Java바이트 코드로 번역한다. 이후 Java바이트 코드를 JVM이 읽고 실행하게 된다.

1.1. 바이트 코드란?

- JVM이 이해할 수 있는 언어로 변환된 자바 소스 코드를 의미한다. 자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불린다. 이러한 자바 바이트 코드의 확장자는. class이며 자바 바이트 코드는 자바 가상 머신만 설치되어 있으면, 어떤 운영체제에서 라도 실행될 수 있다.

1.2. JVM이란?

- JVM은 JavaVirtual Machine의 줄임말로 wirte once, run erveywhere 즉 OS마다 따로 코드를 작성해야 하는 번거로움 업이 Java가 플랫폼에 독립적일 수 있게 만들어준다. 예를 들어 C 프로그램은 바로 기계어로 컴파일하므로 HW 기종에 맞게 컴파일되어야 한다. 이를 '플랫폼에 종속적'이다. 라고 한다. 반면 Java 프로그램은 중간 단계 언어로 컴파일하여 JVM만 각 OS만 설치되어 있다면 HW 기종에 상관없이 단 한 번만 컴파일하면 된다. 이를 '플랫폼에 독립적'이라고 한다. 간단히 말해 JVM은 Java 클래스 파일을 로드하고 바이트 코드를 해석하며, 메모리 등의 자원을 할당하고 관리하며 정보를 처리하는 작업을 하는 프로그램이다.

 

  • JRE는 자바 API와 JVM으로 구성되며, JVM의 역할은 자바 애플리케이션을 클래스 로더를 통해 읽어 들여서 자바 API와 함께 실행하는 것임.
  • 자바 프로그램을 컴파일하면, JVM은 클래스 로더를 이용해서 컴파일된 바이트 코드를 메모리로 읽어들인다.
    class Loader에 의해 바이트코드가 런타임 데이터 영역(Runtime Data Area)에 올라가게 되면 
    실행 엔진(Execution Engine)이 바이트코드를 한줄씩 실행시킨다. 이 과정 속에서 JVM은 필요에 따라 garbage collection 등의 작업을 수행하게 된다.
  • JVM의 메모리 구조는 활용 용도에 따라 여러 영역으로 구분되어 있는데, 메소드, 스택, 힙 영역이 프로그래밍과 관련이 있다.
  • 지정된 클래스에서 main(String[] args)를 호출한다. 
  • Java Compilerava Source파일을 JVM이 해석할 수 있는 Java Byte Code(. class)로 변경한다. 일반적인 윈도우 프로그램의 경우, Compile 이후 Assembly 언어로 구성된 파일이 생성된다.
  • Class LoaderJVM내로. class파일들을 Load 한다. Loading 된 클래스들을 Runtime Data Area에 배치된다. 일반적인 윈도우 프로그램의 경우 Load 과정은 OS가 주도한다.
  • Execution Engine은 Loading 된 클래스의 Bytecode를 해석한다. 이 과정에서 ByteCode가 BinaryCode로 변경된다. 일반적인 윈도우 프로그램의 경우 Assembier가 Assembly언어로 쓰인 코드 파일을 BinaryCode로 변경한다.
  • Runtime Data AreaJVM이 프로세스로써 수행되기 위해 OS로부터 할당받는 메모리 영역이다. 저장 목적에 따라 다음과 같이 5개로 나눌 수 있다.

 

  - Method Area
모든 Thread에게 공유된다. 클래스 정보, 변수 정보, Method정보, static변수 정보, 상수 정보 등이 저장되는 영역
  - Heap Area
모든 Thread에게 공유된다. new 명령어로 생성된 인스턴스와 객체가 저장되는 구역, 공간이 부족해지면 Garbage Collection이 실행된다.
  - Stack Area
각 스레드마다 하나씩 생성된다. Method안에서 사용되는 값들(매개변수, 지역변수, 리턴 값 등)이 저장되는 구역, 메서드가 호출될 때 LIFO로 하나씩 생성되고, 메서드 실행이 완료되면 LIFO로 하나씩 지워진다.
  - PC Register
각 스레드마다 하나씩 생성된다. CPU의 Register와 역할이 비슷하다. 현재 수행 중인 JVM명령의 주소 값이 저장된다.
  - Native Method Stack
각 스레드마다 하나씩 생성된다. 다른 언어(C/C++ 등)의 메서드 호출을 위해 할당되는 구역 언어에 맞게 Stack이 형성되는 구역이다. JNI(Java Native Interface)라는 표준 규약을 제공한다.

+ Recent posts