백준 11723번: 집합 - javascript
백준 11723번: 집합
문제 설명
접기/펼치기
비어있는 공집합 S가 주어졌을 때, 아래 연산을 수행하는 프로그램을 작성하시오.
- add x: S에 x를 추가한다. (1 ≤ x ≤ 20) S에 x가 이미 있는 경우에는 연산을 무시한다.
- remove x: S에서 x를 제거한다. (1 ≤ x ≤ 20) S에 x가 없는 경우에는 연산을 무시한다.
- check x: S에 x가 있으면 1을, 없으면 0을 출력한다. (1 ≤ x ≤ 20)
- toggle x: S에 x가 있으면 x를 제거하고, 없으면 x를 추가한다. (1 ≤ x ≤ 20)
- all: S를 {1, 2, …, 20} 으로 바꾼다.
- empty: S를 공집합으로 바꾼다.
입력
첫째 줄에 수행해야 하는 연산의 수 M (1 ≤ M ≤ 3,000,000)이 주어진다.
둘째 줄부터 M개의 줄에 수행해야 하는 연산이 한 줄에 하나씩 주어진다.
출력
접기/펼치기
check 연산이 주어질때마다, 결과를 출력한다.
예시
접기/펼치기
입력
26
add 1
add 2
check 1
check 2
check 3
remove 2
check 1
check 2
toggle 3
check 1
check 2
check 3
check 4
all
check 10
check 20
toggle 10
remove 20
check 10
check 20
empty
check 1
toggle 1
check 1
toggle 1
check 1
출력
1
1
0
1
0
1
0
1
0
1
1
0
0
0
1
0
접근
문제를 제한조건을 보면 메모리제한이 4MB로 매우 작은 것을 알 수 있다.
물론 아래에 추가로 자바는 448mb c#은 64mb 등 메모리 제한이 추가되어있다
이 문제는 포스팅하는 현재로서는 node.js 를 사용해서 풀 수 없다!..
(그래서 문의를 넣어놨는데, 나중에는 가능 할 지도?)
먼저 이번 문제는 2가지 풀이가 가능하다.
만약 위의 문제를 풀기위해 빈 배열을 두고 매번 명령어에 따라 숫자를 넣거나 제거하고 숫자가 있는지 체크한다고 해보자.
그러면 매번 배열을 탐색하고 삽입,삭제를 해야 될 것이다.
그러면 주어진 메모리안에 코드가 돌아가지 못 할 것이고 우리는 배열에 일일히 넣지않아도 주어지는 명령어에 따른 숫자를 처리해야한다.
힌트는 바로 X의 범위에 있다.
X는 1이상 20이하의 수로 주어진다고 했는데 그러면 관리해야하는 인덱스도 1 ~ 20이다.
그리고 각 인덱스가 기억해야되는건 단 2가지다.
숫자가 존재하는지, 존재하지 않는지.
바로 2진수랑 같다.
2진수의 각 자리수는 2의n제곱값이다. 그러니 원하는 숫자가 들어올때마다 2의 지수로 계산해서 s에 2의 n제곱값을 넣어주면된다.
그리고 비트마스크를 이용해서 or 연산이나 and 연산을 사용하면 해당 비트가 존재하는지, 혹은 해당 비트를 무조건 1으로 변경해 줄 수 있다!
비트연산은 여기를 참고하자.
혹은,
여태 재귀문제를 풀면서 썼던 방법인데, 그냥 boolean 배열을 만들어 써도 된다.
boolean 배열도 각 인덱스값은 true나 false로 나뉘기 때문에 오히려 더 쉽다.
아래의 코드 중 JS코드는 위에서 맨처음에 설명한대로 일단 메모리 초과가 나는 상태이다.
정답이 필요하면 c++로 똑같이 바꿔서 사용하면 된다.
c++코드
접기/펼치기
#include
using namespace std;
int main() { ios::sync_with_stdio(NULL); cin.tie(nullptr); int M,x; int k = 0; string s; cin » M; while (M–) { cin » s; if (s == “add”) { cin » x; if(~(k & (1 «x))) k |= (1 « x); } else if (s == “remove”) { cin » x; if (k & (1 « x)) k &= ~(1 « x); } else if (s == “check”) { cin » x; if (k & (1 « x)) cout « 1 « “\n”; else cout « 0 « “\n”; } else if (s == “toggle”) { cin » x; if (k & (1 « x)) k &= ~(1 « x); else k |= (1 « x); } else if (s == “all”)k |= (1 « 21) - 1; else k = 0; } }
정답 코드
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
let s = 0;
let result = [];
rl.on('line', function (line) {
input.push(line);
})
.on('close', async function () {
// 답안 작성
const n = input.shift()*1;
input.reduce((acc,cur)=>{
let line = cur.split(' ');
bit_set(line[0],Math.pow(2,line[1]*1-1));
},'');
console.log(result.join('\n'));
process.exit();
});
let bit_set = function(cmd,n){
switch(cmd){
case 'add':
s = s|n;
break;
case 'remove':
if((n&s)===n)s-=n;
break;
case 'check':
if((n&s)===n)result.push(1);
else result.push(0);
break;
case 'toggle':
if((n&s)===n)s-=n;
else s+=n
break;
case 'all':
s=0b11111111111111111111;
break;
case 'empty':
s=0;
break;
}
}
정답코드2 boolean 배열사용
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
let s = new Array(21).fill(false);
let result = [];
rl.on('line', function (line) {
input.push(line);
})
.on('close', async function () {
// 답안 작성
const n = input.shift()*1;
input.reduce((acc,cur)=>{
let line = cur.split(' ');
bit_set(line[0],line[1]*1);
},'');
console.log(result.join('\n'));
process.exit();
});
let bit_set = function(cmd,n){
switch(cmd){
case 'add':
s[n] = true;
break;
case 'remove':
s[n] = false;
break;
case 'check':
if(s[n])result.push(1);
else result.push(0);
break;
case 'toggle':
if(s[n])s[n]=false;
else s[n]=true;
break;
case 'all':
s = new Array(21).fill(true);
break;
case 'empty':
s = new Array(21).fill(false);
break;
}
}
댓글남기기