2023. 2. 12. 18:38ㆍ개발/알고리즘 문제풀이
본 글은 백준 2738번 행렬 덧셈 문제를 javascript를 이용하여 풀이한 내용이다.
문제
N*M크기의 두 행렬 A와 B가 주어졌을 때, 두 행렬을 더하는 프로그램을 작성하시오.
입력
첫째 줄에 행렬의 크기 N 과 M이 주어진다. 둘째 줄부터 N개의 줄에 행렬 A의 원소 M개가 차례대로 주어진다. 이어서 N개의 줄에 행렬 B의 원소 M개가 차례대로 주어진다. N과 M은 100보다 작거나 같고, 행렬의 원소는 절댓값이 100보다 작거나 같은 정수이다.
예제 입력
3 3
1 1 1
2 2 2
0 1 0
3 3 3
4 4 4
5 5 100
출력
첫째 줄부터 N개의 줄에 행렬 A와 B를 더한 행렬을 출력한다. 행렬의 각 원소는 공백으로 구분한다.
예제 출력
4 4 4
6 6 6
5 6 100
제한
- 시간 제한 : 1초
- 메모리 제한 : 128MB
1초에 최대 연산 횟수 | |
O(N) | 약 1억번 |
O(N^2) | 약 1만번 |
O(N^3) | 약 500번 |
O(2^N) | 약 20번 |
O(N!) | 10번 |
문제 풀이
해당 문제는 2차원 배열을 연습할 수 있는 가장 기본적인 문제이다.
문제의 설명을 읽어보면 간단해 보이지만 실제로 구현하려고 한다면 당황스러울 수 있다.
특히 입력을 받아오는 방법이 어려울 수 있는데 아래 글에 자세하게 설명되어 있다.
[백준BOJ] JavaScript 입력 받는 방법 종류별 정리 - JavaScript(node.js)
const input = require('fs')
.readFileSync(process.platform === "linux" ? "/dev/stdin" : "./input.txt")
.toString()
.trim()
.split("\n")// \n으로 나누기
.map(el => el.split(" ").map(Number));// map을 통해 각각의 원소들을 공백으로 나눈 뒤 숫자로 변환
큰 덩어리들부터 나누고 그 이후에 잘게 쪼갠다고 생각하면 이해하기 편하다.
"\n"으로 쪼갠 덩어리를 " "로 다시 한번 나누는 것이다.
여기서 입력받은 input을 출력해 보면
[
[ 3, 3 ],
[ 1, 1, 1 ],
[ 2, 2, 2 ],
[ 0, 1, 0 ],
[ 3, 3, 3 ],
[ 4, 4, 4 ],
[ 5, 5, 100 ]
]
위와 같은 결과가 나오게 되는데 원소 안의 원소에 대하여 어떻게 접근해야 할지 모를 수 있다.
input의 3번째 요소의 2번째 요소를 뽑고 싶을 때는
input[2][1]
위와 같이 작성하면 된다.(숫자는 0부터 세기 때문에 input[2][1]이다.)
문제를 풀 때 N, M과 같은 값은 shift()를 통해 다른 변수에 저장하는 겸 input에서 미리 빼두는 것이 다른 문제들을 해결할 때도 좋다.
const [N,M] = input.shift();
이제 2차원 배열을 선언할 차례이다. N X M 크기의 모눈종이를 그린다고 생각하면 된다.
javascript에서는 new연산자로 사용자가 직접 정의한 객체 또는 javascript 내장 객체들을 쉽게 만들 수 있다.
let arr = new Array(N).fill().map(() => new Array(M).fill(0));
new Array(N)를 통해 크기가 N인 배열을 생성한다.
그리고 fill()을 통해 배열 안의 값을 결정하는데 그 값을 undefined로 되게 만들어 둔다.
왜냐하면 map을 통해 각각의 원소들의 값 안에 다시 크기가 M인 배열을 생성하고 그 배열을 0으로 채우기 위함이다.
위 내용을 이해하고 2차원 배열을 선언했다면 이 문제는 거의 해결했다고 봐도 된다.
N의 범위와 M의 범위를 모두 확인해 봐야 하기 때문에 2중 for문을 사용하여 arr에 값들을 집어넣으면 된다.
행렬 A와 B를 만들어둔 2차원 배열인 arr에 더하는 방법이다.
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
arr[i][j] = input[i][j] + input[i + N][j];
}
}
arr[0][0]부터 arr[N-1][M-1]에
A행렬의 범위인 input[0][0]부터 input[N-1][M-1]까지 값을 넣고
B행렬의 범위인 input[N][0]부터 input[N+N-1][M-1]까지 값을 더하는 것이다.
위의 방법까지 하면 출력에 해당하는 값들은 준비되었지만
[ [ 4, 4, 4 ], [ 6, 6, 6 ], [ 5, 6, 100 ] ]
출력 형태가 같지 않기 때문에 출력에 해당하는 형태로 바꿔줘야 한다.
let answer = "";
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[0].length; j++) {
answer += arr[i][j] + " ";
}
answer += "\n";
}
console.log(answer.trim());
문자열로 다시 입력하기 위해 answer을 ""으로 설정해 두고 answer에 각각의 값과 공백을 번갈아가며 넣어주는 방법을 사용한다.
한 줄을 다 넣으면 \n을 통해 다음줄로 넘어가게 한다.
최종 출력 시에는 정답보다 \n이 한 줄 더 추가되어 있기 때문에 trim()을 사용하여 공백을 없애준다.
코드
const input = require('fs').readFileSync(process.platform === "linux" ? "/dev/stdin" : "./input.txt").toString().trim().split("\n").map((el) => el.split(" ").map((el) => +el));
const [N, M] = input.shift();
let arr = new Array(N).fill().map(() => new Array(M).fill(0));
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
arr[i][j] = input[i][j] + input[i + N][j];
}
}
let answer = "";
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[0].length; j++) {
answer += arr[i][j] + " ";
}
answer += "\n";
}
console.log(answer.trim());
마무리
나 또한 해당 문제를 여러 번 풀어보며 2차원 배열에 대한 개념을 익혔다. 2차원 배열에 대한 개념이 잡히고 나면 더 많은 알고리즘 문제들을 쉽게 해결할 수 있을 것이다. 중간중간 출력을 해보면서 과정을 이해하는 시간이 반드시 필요하다.
GitHub 구경하기
'개발 > 알고리즘 문제풀이' 카테고리의 다른 글
[백준BOJ] 24263번 알고리즘 수업 - 알고리즘의 수행 시간 2 - JavaScript(node.js) (0) | 2023.03.05 |
---|---|
[백준BOJ] 24262번 알고리즘 수업 - 알고리즘의 수행 시간 1 - JavaScript(node.js) (0) | 2023.03.05 |
[백준BOJ] 10823번 더하기 2 - JavaScript(node.js) (0) | 2023.02.10 |
[백준BOJ] 2798번 블랙잭 - JavaScript(node.js) (0) | 2023.02.09 |
[백준BOJ] JavaScript 입력 받는 방법 종류별 정리 - JavaScript(node.js) (2) | 2023.02.07 |