개발하는 두부

[Goorm] 파손된 램 (Java)

by 뚜부니

 

 

구름LEVEL

코딩테스트에서 가장 높은 비중을 차지하는 알고리즘 문제를 제작하고 풀이할 수 있는 온라인 저지 서비스입니다. 기업에서 선호하는 C, C++, 파이썬(Python), 자바(Java), 자바스크립트(Javascript) 이

level.goorm.io

 

이 문제는 2의 제곱수의 용량을 가진 램 중에서 파손이 되어 2의 제곱수의 용량을 가지지 않는 램의 수와 번호를 출력하는 문제입니다. 비트 마스크를 이용하면 되게 간단한 문제인데 할 줄 몰라서 열심히 찾아봤네요.. 😂😂

 

2의 n제곱 수를 2진수로 나타내면

2의 0 제곱 : 1 → 1

2의 1 제곱 : 2 → 10

2의 2 제곱 : 4 → 100

2의 3 제곱 : 8 → 1000

과 같이 1로 시작하여 오른쪽을 모두 0으로 채우는 형태입니다.

 

만약 2의 제곱에서 1을 뺀 수를 2진수로 나타내면

2의 0 제곱 - 1 : 0 → 0

2의 1 제곱 - 1 : 1 → 1

2의 2 제곱 - 1 : 3 → 11

2의 3 제곱 - 1 : 7 → 111

과 같이 0 제곱을 제외하고는 모두 1로 이루어진 것을 확인할 수 있습니다.

 

이 사실을 이용하면 임의의 수 n이 2의 제곱수인지 판별이 가능해요! 😎😎

n과 n - 1을 비트 연산자 &를 이용해서 계산했을 때 2의 제곱수이면 결과가 0이 나옵니다.

(& 연산자는 두 수 모두 1이어야 결괏값에 1이 속하게 되기 때문입니다)

즉, n이 2의 제곱수이면 아래와 같은 결과를 얻을 수 있다는 의미입니다.

& 연산 결과

이러한 사실을 적용하여 다음과 같이 문제를 풀 수 있습니다.

import java.io.*;
import java.util.*;

class Main {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine()); // 램 개수
		ArrayList<Integer> error = new ArrayList<>();
		StringTokenizer st = new StringTokenizer(br.readLine());
		for (int i = 1; i <= n; i++){
			int ram = Integer.parseInt(st.nextToken());
			if ((ram & (ram - 1)) != 0) // 2의 제곱이 아닌 경우
				error.add(i);
		}
		
		int errorLen = error.size();
		if (errorLen > 0) {
			System.out.println(errorLen);
			for (int i = 0; i < errorLen; i++)
				System.out.printf("%d ", error.get(i));
		}
		else
			System.out.println(errorLen);
	}
}

 


🔗 Reference

👉 2의 n제곱 수인지 판별하기

블로그의 정보

개발하는 두부

뚜부니

활동하기