본문 바로가기
코딩테스트/자바 Level 2

[Java] 행렬의 곱셈

by onggury 2023. 8. 23.

문제

2차원 행렬 arr1과 arr2를 입력받아, arr1에 arr2를 곱한 결과를 반환하는 함수, solution을 완성해주세요.

 

 

제한사항

  • 행렬 arr1, arr2의 행과 열의 길이는 2 이상 100 이하입니다.
  • 행렬 arr1, arr2의 원소는 -10 이상 20 이하인 자연수입니다.
  • 곱할 수 있는 배열만 주어집니다.

 

class Solution {
    public int[][] solution(int[][] arr1, int[][] arr2) {
        int[][] answer = new int[arr1.length][arr2[0].length];
        
        for(int r = 0; r < arr1.length; r++) {
            for(int i = 0; i < arr1[0].length; i++) {
                for(int j = 0; j < arr2[0].length; j++) {
                    answer[r][j] += arr1[r][i]*arr2[i][j];
                }
            }
        }
        return answer;
    }
}

 

레벨 2부터 왜 이렇게 수학문제가 많은 건지 모르겠다.

최대한 for문을 적게 사용해서 하고 싶었는데 아무리 생각해도 이 방법이 최선의 방법 같았다.

 

행렬의 곱셈은 M×K, K×N 을 무조건 만족해야 할 수 있는 연산이다.

따라서 M×N 크기의 배열을 만들어주고 연산해 준다.

 

일반적으로 손으로 계산할 땐, arr1[0][0]은 arr2[0][0]과 곱하고... arr[0][1]은 arr2[1][0]과 곱하고... 이런 식으로 arr1은 가로로, arr2는 세로로 움직이며 연산을 한다.

그런데 연산되는 방식을 자세히 보면 규칙이 있다.

말로 하는 것보다 예시를 들면,

출처:https://velog.io/@treejy/DP-BOJ-11049%EB%B2%88-%ED%96%89%EB%A0%AC-%EA%B3%B1%EC%85%88-%EC%88%9C%EC%84%9C-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0-1-%EA%B0%9C%EB%85%90

구글에서 가장 이해하기 쉽다고 생각된 그림을 가져와봤다.

A[0][0]은 B[0][0~3]까지 연산해서 C에 담아두고, 이를 A[0][1]과 B[1][0~3]까지 연산한 결과를 더해서 결과물 행렬 C에 저장한다.

결국 B는 [0][0~3], [1][0~3]만 반복하고 이에 따라 A의 각 행의 첫 번째 원소, 두 번째 원소를 연산해 주는 방식이다.

결국 A의 각 행을 가져오기 위한 for문 한 번

A에서 가져온 행의 원소를 하나씩 가져오기 위한 for문 한 번

그 원소를 B의 원소들과 연산하기 위한 for문 한 번

해서 총 for문을 세 번 써야 한다.

 

 

출처

https://school.programmers.co.kr/learn/courses/30/lessons/12949