안녕하세요, 여행벌입니다.

이번 포스팅에서는 변수란 무엇이고, 자바에는 어떤 자료형이 있는지 알아보겠습니다.


변수란 무엇인가.


 "데이터의 저장과 참조를 위해 할당된 메모리 공간에 붙인 이름을 '변수'라 한다."

 즉, 변수는 메모리 공간에 붙여진 이름입니다. 메모리 공간의 할당과 접근 때문에 '변수' 라는 개념이 존재하고, 코드상에서 변수라는 것을 선언하면 메모리 공간이 할당되고 변수명을 이용해 메모리 공간에 접근할 수 있습니다.


자바 자료형의 종류


 변수에 저장할 데이터의 유형을 알리기 위해 앞으로 '자료형(Data Type)' 인 키워드를 변수를 선언할 때 같이 이용할 것입니다. 자바는 다음과 같은 다양한 자료형을 제공합니다.

자료형

데이터

크기

표현 가능 범위

boolean

참과 거짓

1바이트

true, false

char

문자

2바이트

유니코드 문자

byte

정수

1바이트

-128 ~ 127

short

정수

2바이트 

-32,768 ~ 32,767

int

정수

4바이트

-2,147,483,648 ~ 2,147,483,647

long

정수

8바이트

-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

float

실수

4바이트

± (1.40 x 10^-45 ~ 3.40 x 10^38 )

double

실수

8바이트

± (4.94 x 10^-324 ~ 1.79 x 10^308 )

 정리하면 다음과 같습니다.

  • 정수 표현 byte, short, int, long

  • 실수 표현 float, double

  • 문자 표현 char

  • 참과 거짓의 표현 boolean

예를 들어, 2와 3을 저장한 다음 더해서 출력하고 싶다면 다음과 같이 코드를 구현해야 합니다.

package Hello;

public class HelloWorld {
	public static void main(String args[]) {
		int a = 2; //int(정수)를 담는 a라는 이름의 변수에다가 정수 2를 저장하겠다
		int b = 3;
		System.out.println(a + b);
	}
}

 


변수의 이름을 짓는 방법


■ 변수의 이름은 숫자로 시작할 수 없습니다.

■ $과 _ 이외의 특수 문자는 변수의 이름에 사용할 수 없습니다.

■ 키워드는 변수의 이름으로 사용할 수 없습니다.

     ( int, double 같은 키워드는 변수명으로 사용할 수 없습니다.)


자바의 기본 자료형


■ 정수 자료형 : byte, short, int, long

 자바는 총 4개의 정수 자료형을 제공합니다. 차이점은 이용하는 저장 공간의 크기로 저장 공간이 클수록 더 많은 값을 표현할 수 있습니다. 보통 프로그래밍을 하다보면 int, long 형을 많이 사용하게 되는데 그 이유는 다음과 같습니다.

 "자바는 정수형 연산을 기본적으로 int형으로 진행합니다."

 즉, short 형 변수 2개를 더하면 error가 발생합니다.

package Hello;

public class HelloWorld {
	public static void main(String args[]) {
		short a = 2;
		short b = 3;
		short result;
		result = a + b;
	}
}

 short 형 변수 result에 short 형 변수 a와 b를 더해서 저장했습니다. 하지만 자바는 정수형 연산을 int 형으로 진행하므로 a + b 한 결과값은 int 형이 됩니다. 따라서 위의 코드는 에러가 발생합니다.

( # long 형 변수는 이미 int 형 보다 더 많은 값을 저장하고 있으므로 long 형으로 연산이 진행됩니다. )

 

■ 실수 자료형 : float, double

 소수점 이하의 값을 지니는 실수의 저장 및 표현을 위한 자료형은 float 과 double로 저장 공간 크기에 따라 표현할 수 있는 범위가 다릅니다. 하지만, 이 둘 모두 정밀도를 포기하고 표현의 범위를 넓힌 자료형들이기 때문에 정확히 실수 값을 다룰 수 없습니다.

 쉽게 얘기하면 실수 자료형 연산은 우리가 생각하는 것과 다르게 오차가 발생할 수밖에 없습니다. 예를 들어, 0.1 을 2진법으로 표현하면 0.00010001⋯ 으로 무한한 공간이 필요합니다.

 즉, 컴퓨터는 실수를 제대로 저장할 수 없다.

 

■ 문자 자료형 : char

 문자 자료형 char는 유니코드를 이용해 문자를 저장합니다. 유니코드는 문자 하나를 2바이트로 표현하는 문자 체계로 대다수 언어의 기본 문자를 표현할 수 있는 문자 체계입니다. 자바의 char는 문자의 저장을 위한 자료형으로 변수 하나에 문자 하나만 저장하는 것이 가능합니다.

 

■ 논리 자료형 : boolean

 true : '참' 을 의미하는 값

 false : '거짓'을 의미하는 값으로 논리자료형 boolean 은 '참'과 '거짓'의 상황 또는 상태를 표현하는 자료형입니다.


 


[ 알고리즘풀이 ]

우리는 현재 탑에서 지금까지 순회한(왼쪽에 있는 탑들) 탑 중 나보다 높이가 큰 가장 가까운 탑을 고르면 된다.

- 왼쪽부터 순회하며 자료구조 Stack을 이용하면 문제를 간단히 해결할 수 있다.

- 현재 Stack이 비어있다면, 나보다 큰 탑이 없는 걸로 판단하고 answer에 '0', Stack에 현재 탑을 Push.

- Stack이 비어있지않다면, 나보다 큰 탑을 찾을 때까지 Stack을 Pop한다. 나보다 작은 탑들(Pop되는 탑들)은 어차피 나보다 작은 탑이라 앞으로 오른쪽 탑에서 보내는 수신 신호를 받지 못한다.

#include <string>
#include <stack>
#include <vector>

using namespace std;

vector<int> solution(vector<int> heights) {
    vector<int> answer;
    stack<pair<int, int>> s;
    for (int i = 0; i < heights.size(); i++) {
        while (!s.empty()) {
            if (s.top().first <= heights[i]) {
                s.pop();
            }
            else {
                answer.push_back(s.top().second);
                s.push({ heights[i], i + 1 });
                break;
            }
        }
        if (s.empty()) {
            answer.push_back(0);
            s.push({ heights[i], i + 1 });
        }
    }
    return answer;
}

 

문제 : https://www.acmicpc.net/problem/17779


[ 알고리즘풀이 ]

■ 처음엔 5번 선거구를 먼저 정하고, 남는 자리에 한해서 아래를 만족하면 1, 2, 3, 4번 선거구로 정하려고 했다. 그러면 5번 선거구만 정하고 나머지는 전체를 순회하며 단순 if 문 만으로 처리할 수 있기 때문에 구현이 깔끔할 것 같았다.

  • 1번 선거구: 1 ≤ r < x+d1, 1 ≤ c ≤ y

  • 2번 선거구: 1 ≤ r ≤ x+d2, y < c ≤ N

  • 3번 선거구: x+d1 ≤ r ≤ N, 1 ≤ c < y-d1+d2

  • 4번 선거구: x+d2 < r ≤ N, y-d1+d2 ≤ c ≤ N

하지만, 5번 선거구를 먼저 선정하려면 다이아몬드를 그려야되는데 이 부분이 구현하기 어려워, 결국 1, 2, 3, 4 번 선거구를 정하고 남는 부분을 5번 선거구로 정했다.

■ 모든 x, y, d1, d2에 대해서 게임을 진행하고, 애초에 5개 구역으로 못나누는 경우는 return, 아니라면 선거구를 나누며 답을 갱신하면 된다.

#include<iostream>
#include<algorithm>
#define INF 987654321
using namespace std;

int N, map[21][21] = {}, ans = INF;

void separate(int x, int y, int d1, int d2) {
	// 애초에 5개 구역으로 못나누는 경우.
	if (!(1 <= x && x + d1 + d2 <= N && 1 <= y - d1 && y + d2 <= N))
		return;

	int label[21][21] = {}, sum[5] = {};
	// 1구역
	for (int r = 1; r < x + d1; r++) {
		if (r < x)
			for (int c = 1; c <= y; c++)
				label[r][c] = 1;
		else
			for (int c = 1; c <= y - (r - x + 1); c++)
				label[r][c] = 1;
	}
	// 2구역
	for (int r = 1; r <= x + d2; r++) {
		if (r <= x)
			for (int c = y + 1; c <= N; c++)
				label[r][c] = 2;
		else
			for (int c = y + 1 + (r - x); c <= N; c++)
				label[r][c] = 2;
	}
	// 3구역
	for (int r = x + d1; r <= N; r++) {
		if (r < x + d1 + d2)
			for (int c = 1; c < y - d1 + (r - (x + d1)); c++)
				label[r][c] = 3;
		else
			for (int c = 1; c < y - d1 + d2; c++)
				label[r][c] = 3;
	}
	// 4구역
	for (int r = x + d2 + 1; r <= N; r++) {
		if (r <= x + d1 + d2)
			for (int c = y + d2 + 1 - (r - (x + d2)); c <= N; c++)
				label[r][c] = 4;
		else
			for (int c = y - d1 + d2; c <= N; c++)
				label[r][c] = 4;
	}
	for (int r = 1; r <= N; r++)
		for (int c = 1; c <= N; c++)
			sum[label[r][c]] += map[r][c];

	sort(sum, sum + 5);
	ans = min(ans, sum[4] - sum[0]);
	return;
}

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	cin >> N;
	for (int i = 1; i <= N; i++)
		for (int j = 1; j <= N; j++)
			cin >> map[i][j];

	
	// d1, d2, x, y 마다 게임을 진행하자.
	for (int d1 = 1; d1 <= N; d1++)
		for (int d2 = 1; d2 <= N; d2++)
			for (int x = 1; x <= N; x++)
				for (int y = 1; y <= N; y++)
					separate(x, y, d1, d2);
	
	cout << ans;
}

 


[ 알고리즘풀이 ]

3진법처럼 n을 3으로 나눠가면서 나머지에 따라 값을 answer에 변환되는 수를 쌓고, 반대로 출력해주면 된다.

#include <string>
#include <vector>
#include <algorithm>
using namespace std;

string solution(int n) {
	string answer = "";
	while (n) {
		if (n % 3 == 1)
			answer += '1';
		else if (n % 3 == 2)
			answer += '2';
		else
			answer += '4';
		n--;
		n /= 3;
	}
	reverse(begin(answer), end(answer));
	return answer;
}

 

+ Recent posts