상수

선언 방법

  • 상수는 final을 이용하여 변수를 선언한다.
  • final을 사용하면 값을 변경할 수 없다.
  • final 앞에 static을 붙여 클래스가 로드될 때 미리 생성해둔다.
  • 여러 단어로 되어 있는 상수는 단어 사이에 _(underbar)로 구분한다.
private static final MIN_SPEED = 1;

클래스 선언

  • 클래스 내부의 값은 변경할수 있다.
class Sample {
	public int num = 0;
 	...
}

private static Sample sp = new Sample();

sp = new Sample(); // final로 선언된 변수 변경 불가
sp.num = 10; // 클래스의 변수 변경 가능

리터럴

  • 리터럴은 변하지 않는 직접 입력된 데이터, 즉시 값(immediate value)이라고 한다.
  • 아래의 예시와 같이 100L, 1.5F, 1.5D와 같은 값을 리터럴이라고 한다.
Long l = 100L;
Float f = 1.5F;
Double d = 1.5D;
String s = "가";
char c = 'A';
boolean b = true;

리터럴 접미사

  • Long : L 또는 l
  • Float : F 또는 f
  • Double : D 또는 d (생략 가능)

기본형 (Primitive Type)

종류 자료형 범위 bit byte
논리형 boolean false, true 8 1
문자형 char \ u0000 ~ \ uffff (0~216 - 1) 16 2
정수형 long -9,223,372,036,854,775,808 ~ 0 ~ 9,223,372,036,854,775,807 64 8
int - 2,147,483,648 ~ 0 ~ 2,147,483,647 32 4
short -32,768 ~ 0 ~ 32,767 16 2
byte -128 ~ 0 ~ 127 8 1
실수형 double 4.9E-324 ~ 1.8E308 64 8
float 1.4E-45 ~ 3.4E38 32 4
  • 논리형 : boolean을 제외한 나머지 7개의 기본형은 서로 연산이 가능하다. 1bit로 충분하지만 자바는 최소 단위가 1byte이다.
  • 문자형 : 내부적으로 정수(유니코드)로 저장하기 때문에 정수형과 다르지 않으며 정수형, 실수형과 연산이 가능하다. 컴퓨터는 숫자 밖에 모르기 때문에 모든 데이터를 숫자로 변환하여 저장한다.
  • 정수형 : CPU가 가장 효율적으로 처리할 수 있는 타입이며 메모리 절약 시 byte, short를 사용한다.
  • 실수형 : 소수 점을 표현하며 각 자료형마다 소숫점의 자리 수와 오차가 다르다.

실수형의 정밀도

자료형 정밀도 bit byte
float 7자리 32 4
double 15자리 64 8
  • 정밀도가 높을 수록 오차 범위가 줄어든다.

각 자료형의 범위

-2^n-1 ~ 2^n-1 - 1이며, n은 자료형의 bit 수이다.
int의 경우 bit가 4byte * 8bit = 32bit라서 -2^31 ~ 2^31 - 1이다.

 

참조형 (Reference Type)

  • 참조형은 객체의 메모리 주소를 저장한다.
  • 참조형은 객체의 종류에 의해 구분되므로 타입이라 칭한다.
  • String, Integer, Boolean, List 등 클래스가 참조형 타입니다.
Date date = new Date();
Sample sp = new Sample();
  • 참조형 변수는 객체의 메모리 주소를 참조한다. ex) date, sp
  • 객체에 사용된 클래스를 객체의 타입이라고 한다. ex) Date, Sample

래퍼 클래스 (Wrapper Class)

  • 기본형의 8가지 자료형을 객체로 사용하기 위한 클래스
기본형 (Primitive Type) 래퍼 클래스 (Wrapper Class)
boolean Boolean
char Character
long Long
int Integer
short Short
byte Byte
double Double
float Float
  • char, int형을 제외하고 나머지 자료형은 각 자료형의 첫 글자를 대문자로 바꾸면 클래스가 된다.

래퍼 클래스 (Wrapper Class) 상속 관계도

  • Boolean, Character 클래스를 제외한 래퍼 클래스는 Number라는 상위 클래스와 상속 관계에 있다.

Boxing과 UnBoxing

  • JDK 1.5 이전에는 기본형과 래퍼 클래스 간 연산이 불가능하였다.
  • 현재는 컴파일러가 intValue와 같은 메서드를 붙여 기본형과 래퍼 클래스 간의 연산이 가능해졌다.
// JDK 1.5 이전

int i = 5;
Interger j = 5;
i+j; //에러 발생

//JDK 1.5 이후
int i = 5;
Integer j = 5;
i+j.intValue(); //intValue()로 자료형 int를 받아 연상

Boxing & UnBoxing

  • Boxing : 기본형을 래퍼 클래스로 변환하는 것을 의미한다.
  • UnBoxing :
  • 래퍼 클래스를 기본형으로 변환하는 것을 의미한다.
Integer i = new Integer(100); // Boxing
int j = i.intValue(); // UnBoxing

Auto Boxing & Auto UnBoxing

Integer i = 17; // Auto Boxing
int j = i; // Auto UnBoxing

Boxing & UnBoxing Compile 비교

// 컴파일 전
Integer int = (Integer) x;
Object o = (Object) x;
Long l = 100L;


// 컴파일 후
Integer int = Integer.valueOf(x);
Object o = (Object) Integer.valueOf(x);
Long l = new Long(100L);

기본형과 참조형의 비교

Integer num1 = new Integer(100);
Integer num2 = new Integer(100);
int num3 = 100;

num1 == num2; // 참조형과 참조형 비교 false

num1 == num3; // 참조형과 기본형 비교 true
num1.equals(num3) // equals를 이용한 참조형과 기본형 비교 true;

클래스, 인터페이스

  • 첫 글자는 항상 대문자로 한다.
  • 주로 명사로 명명한다.
  • 여러 단어로 이루어진 이름일 경우 단어의 첫 글자를 대문자로 한다. (Pascal Case)
    class ClassName
    interface InterfaceName​

메서드

  • 첫 글자는 항상 소문자로 한다.
  • 주로 동사로 명명한다.
  • 여러 단어로 이루어진 이름일 경우 단어의 첫 글자를 대문자로 한다. (Camel Case)
    public int get() {
    	...
    }
    
    public boolean set(int n) {
    	...
    }
    
    public String findName() {
    	...
    }
    
    public int getBackNumber(String name) {
    	...
    }
  • 생성자의 경우 첫 글자를 대문자로 한다. (Pascal Case)
    class ClassName {
    
    	public ClassName() {
        	...
        }
        
    }​

변수

  • 첫 글자는 항상 소문자로 한다.
  • 한 글자로 된 변수는 지양한다.
  • 변수에 약어를 사용하지 않고 충분한 사용 의미를 담는다.
  • 여러 단어로 이루어진 이름일 경우 단어의 첫글자를 대문자로 한다. (Camel Case)
    private int number = 0;
    private String userName = "이름";
    private boolean isSuccess = true;​

패키지

  • 모든 패키지 명은 소문자로 한다.
    com.sample.package.router
    com.sample.package.handler
    com.sample.package.service​

상수

  • 모든 글자를 대문자로 한다.
  • 여러 단어로 이루어진 이름일 경우 _(underbar)로 구분한다. (Snake Case)
    private static final int MAX;
    private static final int MIN;
    private static final int MAX_VALUE;
    private static final int MIN_VALUE;​
문제 링크 : https://www.acmicpc.net/problem/13305
문제 등급 : Silver IV
 

13305번: 주유소

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에는 도시의 개수를 나타내는 정수 N(2 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 인접한 두 도시를 연결하는 도로의 길이가 제일 왼쪽 도로부터 N-1

www.acmicpc.net

문제 해결 로직

  1. 리터당 가격을 기준으로 반복문을 돌린다.
  2. 이전 리터의 가격과 현재 리터의 가격을 비교하여 작은 값을 기록한다.
  3. 작은 값으로 거리와 곱해 주유 비용을 계산한다.

위의 로직을 보면 매우 간단하다.

하지만 처음 문제를 풀었을 때 17점을 받았었다.

 

간단히 공유하자면

1. 이전 도시에서 주유한 주유비와 현재 도시의 주유 비와 앞으로 갈 전체 거리를 계산하여 기록하였다.

2. 이전의 주유비와 비교하여 작은 값을 기록하였다.

3. 앞으로 간 거리만큼 전체 거리에서 빼주고 이전 도시에서 주유한 주유비를 기록하였다.

long tot = Integer.MAX_VALUE, stat = 0;

for(int i = 0; i < dis.length; i++) {
  long d = dis[i];
  long a = Long.parseLong(amounts[i]);
  tot = Math.min(tot, stat + (a * totDis));
  totDis -= d;
  stat += (a * d);
}

위의 1~3번을 반복하면 가장 작은 값의 주유비가 나온다 하지만 값이 너무 커질 수 있다.

BigInteger로 구현해도 17점이였다. 

차이점은 틀린 로직에서 불필요한 계산이 들어가는것 밖에 없었는데 17점을 받았다.

메모리나 시간상의 문제도 없었다.

왜 틀렸는지 의문이지만 해결된 로직이 더 간결하긴하다...

 

아래와 같이 해결 로직의 소스를 공유합니다.

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

        br.readLine();

        String[] dis = br.readLine().split(" ");
        String[] amounts = br.readLine().split(" ");

        long min = Long.parseLong(amounts[0]), tot = 0;
        
        for (int i = 0; i < dis.length; i++) {
            long d = Long.parseLong(dis[i]);
            long a = Long.parseLong(amounts[i]);

            if(a < min) min = a;

            tot += (min * d);
        }

        System.out.println(tot);
    }
}

+ Recent posts