Maximum Subarray - LeetCode

Can you solve this real interview question? Maximum Subarray - Given an integer array nums, find the subarray with the largest sum, and return its sum.   Example 1: Input: nums = [-2,1,-3,4,-1,2,1,-5,4] Output: 6 Explanation: The subarray [4,-1,2,1] has t

leetcode.com

문제 분석

  • Input
    정수 배열 nums

  • Output
    합이 가장 큰 부분 배열의 합

  • Constraints
    부분 배열이라 함은, 인덱스가 비어있지 않은 구간의 집합을 의미.

  • Time complexity
    ※1초에 1억 번을 대략적인 기준으로 삼는다.
    $1 \le nums.size \le 100'000$이므로, $O(n log n)$ 이하의 복잡도부터 고려해 볼 수 있다.

 

해결 과정

먼저 만만한 완전탐색이 가능한지 확인,
= 가능하다, 근데 시간이 $O(n^2)$이라 다른 방법 찾아야 함


그럼 DP로 변환 가능?
= 생각 해봐야함

 

dp[i] = i번째 까지 최대 합의 값?  이라고 정의하면, 최대 값 부분배열의 마지막이 어딘지 같은 부가 데이터를 또 관리해야 한다.

= 다음 값 계산하기가 어러워 다른 정의가 필요하다.

 

dp[i] = i번째 원소에서 끝나는 부분 배열의 최대 합의 값? 이라고 하면  한번의 순회로 끝낼 수 있을 것 같았다.

해당 상태는 i번째 원소가 이전 부분배열을 잇거나, 부분배열의 시작이 되던지 두 상태중 하나로 표현가능하다.

 

즉, 점화식은 dp[i] = max(dp[i-1] + input[i], input[i]) 와 같다.

 

진행하다 보면 최대 합의 값이 낮아질 수 있는데, 역대 최대 합의 값 중 가장 큰 값을 저장하면 되기 때문에 별 문제없을 거라고 생각했다.

 

 

코드 구현

직전 상태만 참조하면 되기 때문에 굳이 테이블을 만들지 않고 진행했다.

int maxSubArray(vector<int>& nums) 
{
    // Initialize
    int dp = nums[0];
    int result = dp;

    // Do dp
    for (int i = 1; i < nums.size();++i)
    {
        dp = std::max(dp + nums[i], nums[i]);
        result = std::max(result, dp);
    }

    // Return
    return result;
}

 

 

되돌아보기

옛날에는 점화식 상태를 ~번째까지의 최대/최소 값으로만 생각했었는데, 다행히 이번에 상태를 잘 정의하여 수월하게 풀었던 것 같다.

점화식 이전에 어떤 것을 상태로 저장해야 다음 상태를 계산할 수 있는지 생각하는 것이 중요하다고 한 번 더 생각하게 되는 문제였다.

문제 분석

  • Input
    정수 배열 nums

  • Output
    훔칠 수 있는 최대 금액

  • Constraints
    i번째 집을 훔치면, 인접한 i-1, i+1의 집은 훔칠 수 없다.
    첫번째 집과 마지막집이 인접하다고 가정한다.

  • Time complexity
    ※1초에 1억 번을 대략적인 기준으로 삼는다.
    입력값의 개수 범위가 $1 \le n \le 100$이기 때문에, $O(n^2)$부터 고려해볼 수 있다.

 

 

해결 과정

일일히 다 해보면 되지만, 이전 상태 값에서 업데이트하는 것도 괜찮아 보임.
dp[i] = i번째 집까지 순회했을때 훔칠 수 있는 최대 금액

훔치거나 훔치지 않거나의 상태가 있으므로 최종적으로 아래처럼 가능
dp[i][0] = i번째 집까지 순회하고, i번째 집을 털었을 때의 최대 금액
dp[i][1] = i번째 집까지 순회하고, i번째 집을 털지 않았을 때의 최대 금액

i번째 집을 털고 난 후 의 최대 금액은 i-1번째 집을 털지 않은 최대 금액을 더해주면 되고,
i번째 집을 털지 않은 후 의 최대 금액은 i-1번째 집을 털거나, 털지 않은 금액중 최대 값이다.


그래서 점화식은 아래와 같다.
dp[i][0] = dp[i-1][1] + input[i]
dp[i][1] = max(dp[i-1][0], dp[i-1][1])

근데 중요한 건 각 값에 첫 번째 집을 털었는지에 대해 알 수 없다는 거다;
그래서 마지막 집을 털수 있는지의 여부 또한 알기 힘들다.

그래서 첫 번째 집을 털었을때와 털지 않았을 경우로 DP를 두 번 돌릴 예정이다.
시간은 DP한 번당 O(n)정도니까 충분한 시간내에 통과 가능할 것이라고 생각한다.

 

구현

int rob(vector<int>& nums) 
    {
        
        if (nums.size() == 1) return nums[0];

        int retA, retB;        

        // 첫 번째 집을 털었을 때
        {
            // Initialize
            int dp[101][2] = {0};
            dp[0][0] = dp[1][1] = nums[0]; // 두 번째 집은 없다고 생각해도 된다.

            // fill in dp table
            for (int i = 2; i < nums.size() - 1; ++i) // 마지막 집은 찾지 않아도 된다.
            {
                dp[i][0] = dp[i-1][1] + nums[i];
                dp[i][1] = std::max(dp[i-1][0], dp[i-1][1]);
            }

            // Set result candidate
            retA = std::max(dp[nums.size() - 2][0], dp[nums.size() - 2][1]);
        }

        // 첫 번째 집을 털지 않았을 때
        {
            // Initialize
            int dp[101][2] = {0};
            dp[1][0] = nums[1]; // 첫번째 집은 없다고 생각해도 된다.
            
            // fill in dp table
            for (int i = 2; i < nums.size(); ++i) // 마지막 집까지 찾아야 한다.
            {
                dp[i][0] = dp[i-1][1] + nums[i];
                dp[i][1] = std::max(dp[i-1][0], dp[i-1][1]);
            }

            // Set result candidate
            retB = std::max(dp[nums.size() - 1][0], dp[nums.size() - 1][1]);
        }

        // Result
        return std::max(retA, retB);
    }

 

 

되돌아보기

통과는 했지만 아쉬운 점이 있다!

문제 해석

첫 번째 집을 터는 경우, 털지 않는 경우 이렇게 두 경우로 나누어 생각한 것이 방향은 맞지만,
표현을 굳이굳이 복잡하게 한 느낌이라 이를 코드로 표현하는 과정에서 오히려 복잡해졌었던 것 같다.

 

이 경우에는 첫 번 째 문제로, 초기 값의 논리가 어색한 문제가 있다.

첫 번째 집을 턴다고 가정할때, dp[1][0]의 경우는 두 번째 집을 턴 최대 금액? 이란 모순이 생긴다.

 

두 번째 문제로, 반복문 범위의 세부사항이다.

그래서 DP테이블을 채우는 알고리즘이 똑같아도 굳이 두 번을 작성한 셈이다.

이러한 문제는 표현을 간단하게 하면 해결되는데,  바로 구간을 두 가지로 생각하는 방법이다.

  • 마지막 집을 제외하고 [0, n-2] 구간을 털기
  • 첫 번째 집을 제외하고 [1, n-1] 구간을 털기

이렇게 하면 초기 값 논리도 어색하지 않고, 하나의 알고리즘 코드에 구간만 다르게 넣어 풀이를 수행할 수 있다.

 

 

개선 코드

아쉬운 부분을 개선하여 다시 풀어보았다.

int Solve(const vector<int>& nums, int s, int e)
{
    // Initialize
    int dp[101][2] = {0};
    dp[s][0] = nums[s];

    // fill in dp table
    for (int i = s + 1; i < e; ++i)
    {
        dp[i][0] = dp[i-1][1] + nums[i];
        dp[i][1] = std::max(dp[i-1][0], dp[i-1][1]);
    }

    // Return result
    return std::max(dp[e - 1][0], dp[e - 1][1]);
}

int rob(vector<int>& nums) 
{
    if (nums.size() == 1) return nums[0];

    // Do Solve       
    int candidate1 = Solve(nums, 0, nums.size() - 1);
    int candidate2 = Solve(nums, 1, nums.size());
    
    // Result
    return std::max(candidate1, candidate2);
}

 

추가로 DP테이블에서 바로 직전상태만 참고하면 되기 때문에 배열을 사용하지않고도 풀이해봤다.

int Solve(const vector<int>& nums, int s, int e)
{
    // Initialize
    int robMax = nums[s];
    int notRobMax = 0;
    
    // Do DP
    for (int i = s + 1; i < e; ++i)
    {
        int rob = notRobMax + nums[i];
        int notRob = std::max(robMax, notRobMax);
        
        robMax = rob;
        notRobMax = notRob;
    }

    // Return
    return std::max(robMax, notRobMax);
}

int rob(vector<int>& nums) 
{
    // Handling exceptions if number size is 1
    if (nums.size() == 1) return nums[0];

    int candidate1 = Solve(nums, 0, nums.size() - 1);
    int candidate2 = Solve(nums, 1, nums.size());

    // Result
    return std::max(candidate1, candidate2);
}

위수와 동차연립방정식

2장에서 일차연립방정식을 행렬방정식 $AX =B$ 형태로 표현하고,
확대행렬 $(A\mid B)$를 만들어 적절한 기본행연산을 적용하여 해를 구할 수 있었다.

 

여기서 $AX =B$의 해집합도 알아보았는데, 행렬을 직접보고 판단했었다.

이번에는 위수와 동차연립방정식을 이용하여 해집합의 특징을 좀 더 일반화한 표현으로 알아본다.

 

 

위수(rank)

행렬 M에 기본행연산을 적용하여 행제형 행렬 R로 만들었을 때, 영행이 아닌 행의 수를 위수라고 한다.

예를 들어 다음 행제형 행렬을 보자.

 

$A=\begin{pmatrix}
1 & 0 & 2 \\
0 & 1 & 3 \\
0 & 0 & 0
\end{pmatrix}$

 

여기서 $0$이 아닌 행은 2개고, 따라서 이 행렬의 위수는 2이다.
$rank(A) = 2$

 

이 표현식이 뜻하는 바는 다음과 같다.

  • 행렬A에는 독립적인 방정식이 2개가 있다.
  • 피벗이 2개가 있다.

따라서 위수는 기존에 배웠던 내용을 더 간단하게 말할 수 있는 도구로 볼수도 있는 것 같다.

 

확대행렬의 위수

확대행렬 또한 위수를 구할 수 있다.
행제형행렬 A와 상수행렬 B를 이용해 확대행렬을 만들면 다음과 같다.

 

$(A \mid B) =\left(\begin{array}{ccc|c}1 & 0 & 2 & b_1 \\0 & 1 & 3 & b_2 \\0 & 0 & 0 & b_3\end{array}\right)$

 

행렬 $A$의 3행은 영행이어서 위수가 2였지만,
확대행렬에서 3행은 $b_3(단,b_3\neq0)$로 인해 영행이 아니게되어 위수가 3이된다.

 

이때 위수를 정리하면 다음과 같다.

$rank(A) = 2\\rank(A∣B)=3$

 

여기서 중요한 건 3행을 방정식으로 표현하면 $0x+0y+0z=b_3$인데, 이는 불가능한 식으로 모순되는 식이 발생한다.
그래서 이를 통해 $rank(A) < rank(A\mid B)$ 면 모순되는 식이 있다고 판별할 수 있다.

 

위수의 성질

이전에 배웠던 행렬방정식의 해집합의 특징은 아래와 같다.

  • 하나의 해만 존재한다.
    • 자유변수가 존재하지 않는다.
    • 모든 변수 열에 선도원소가 존재한다.
  • 무수히 많은 해
    • 하나 이상의 자유변수가 존재한다.
    • 모든 식이 서로 모순되지 않는다.
  • 해가 없는 경우
    • 행연산 결과 모순이 발생한다.
    • 다음 형태의 행이 존재한다
      $(0\ 0\ \cdots\ 0 \mid k)\ (단, k\neq 0)$

이제는 해당 내용을 위수로 압축해서 표현할 수 있다.
(방정식이 $m$개이고 미지수가 $n$개인 일차연립방정식을 $AX=B$와 같이 행렬방정식으로 나타냈다고 가정한다.)

  • 하나의 해만 존재한다.
    $rank(A)=rank(A∣B)=n$
  • 무수히 많은 해
    $rank(A)=rank(A∣B)<n$
  • 해가 없는 경우
    $rank(A)<rank(A∣B)$

 

동차연립방정식 (Homogeneous linear system)

위수로 일반적인 연립방정식 $AX= B$의 해집합을 판정할 수 있었다.
이제는 동차연립방정식 $AX=O$은 정방행렬 $A$가 정칙행렬인지 판정하는 방법을 알아본다.

 

$AX = B$ 에서 상수행렬 $B$ 가 영행렬 $O$인 경우를 동차연립방정식이라고 한다.
그래서 $AX = O$로 표현할 수 있다.

 

예를들어 $\begin{cases}x + 2y = 0 \\2x + 4y = 0\end{cases}$ 처럼 오른쪽 상수 부분이 전부 0이면 동차연립방정식이다.

 

자명한 해 & 자명하지 않은 해

여기서 중요한 점은, 동차연립방정식은 항상 적어도 하나의 해를 가진다는 것이다.
왜냐하면 모든 미지수에 0을 넣으면 식이 성립되기 때문이다.

 

그래서 모든 미지수가 0이 해를 자명한 해라고 한다.
반대로, 미지수 중 하나라도 0이 아닌 해를 자명하지 않은 해라고 한다.

 

만약 서로 다른 두 입력 $X_1, X_2$가 같은 결과를 만든다면,

$AX_1 = AX_2$ 가 된다.

 

양변을 정리하면 $A(X_1-X_2)=O$ 이다.

 

즉, 두 입력의 차이 $X_1-X_2$는 동차연립방정식 $AX=O$의 해가 된다.

 

만약 $X_1 \neq X_2$라면, $X_1-X_2 \neq O$ 이므로,
$AX=O$에 자명하지 않은 해가 존재한다는 뜻이다.

 

따라서 $AX=O$에 자명하지 않은 해가 있으면 서로 다른 입력이 같은 결과를 만들 수 있고,
이 경우 $A$는 되돌릴 수 없다. 즉, 역행렬이 존재하지 않는다.

 

반대로 $AX=O$가 자명한 해 $X=O$만 가진다면, 서로 다른 입력이 같은 결과를 만들 수 없다.
정방행렬에서는 이 조건이 곧 $A$가 정칙행렬이라는 뜻이다.

 

따라서 정방행렬 $A$에 대해 다음이 성립한다.

$(AX=O \text{가 자명한 해만 가진다})$$\Longleftrightarrow$$A \text{는 정칙행렬이다}$

'컴퓨터 공학 > 선형대수학' 카테고리의 다른 글

04. 역행렬(2)  (0) 2026.06.29
04. 역행렬(1)  (0) 2026.06.24
03. 행렬의 연산  (0) 2026.06.23
02. 연립방정식과 행렬  (0) 2026.06.22
01. 일차방정식  (0) 2026.06.18

기본행렬(Elementary matrix)

n차 단위 행렬 $I_n$에 기본행연산을 한 번만 적용하여 얻는 행렬 $E$를 기본행렬 이라고 한다.

기본행 연산이 세 가지 있으니, 기본행렬또한 세 종류가 있다.
각 세가지는 아래와 같이 표현한다.

  • $E_{i,j}$ : 두 행을 교환하여 얻은 기본행렬
  • $E_i(c)$ : i번째 행에 0이 아닌 상수 $c$를 곱하여 얻은 기본행렬
  • $E_{i,j}(c)$ : i번째 행에 j번째 행의 $c$배를 더하여 얻은 기본행렬

행렬 $A$에 기본행연산 $R$을 적용한 결과를 $R(A)$라고 한다.

 

특징

먼저 행렬 $A$를 $n \times p$ 행렬이라고 가정하고 설명한다.

  • $R(A) = EA$
    $R(A)$ : 행렬 $A$에 기본행연산 $R$을 적용한 결과
    $E$ : $n$차 단위행렬 $I_n$에 같은 기본행연산 $R$을 적용하여 얻은 행렬

    여기서 중요한 점은 기본행렬 $E$를 왼쪽에 두고 곱한다는 것이다.
    $E$를 행렬 $A$의 왼쪽에 곱하면 $A$의 행이 변하고,
    반대로 오른쪽에 곱하면 일반적으로 행이 아니라 열이 변한다.

    따라서 행 연산은 왼쪽에 둔 곱셈으로 표현하고, 열 연산은 오른쪽에 둔 곱셈으로 표현할 수 있다.

  • A와 B가 행상등하다면 $A = E_1E_2 \cdots E_kB$ 가 성립한다.
    두 행렬 $A$와 $B$가 행상등하다는 것은, 기본행연산을 유한 번 적용하여 한 행렬을 다른 행렬로 바꿀 수 있다는 뜻이다.
    따라서 $A$와 $B$가 행상등하다면, 유한개의 기본행렬 $E_1, E_2, \cdots, E_k$가 존재하여 $A = E_1E_2 \cdots E_kB$ 같이 나타낼 수 있다.
    즉, 행렬 $B$에 여러 기본행연산을 적용하면 $A$를 만들 수 있는 것이다.

    반대로 $A$에서 $B$로 가는 방향으로 기본행연산을 잡으면 다음과 같이 쓸 수도 있다.
    $B = F_1F_2 \cdots F_mA$

성질

  • 기본행렬은 모두 정칙행렬이며, 기본행렬의 역행렬도 같은 종류의 기본행렬이다.
    예를 들어, 두 행을 교환하는 기본행렬은 같은 두 행을 다시 교환하면 원래대로 돌아간다.
    $E_{i,j}^{-1} = E_{i,j}$

  • A가 n차 정칙행렬이라면 A는 영행이나 영렬이 없다.
    왜냐하면 영행이나 영렬이 존재한다면, 결과또한 영행이나 영령이 존재하게 되어, 단위행렬을 만들 수 없게된다.
    $AA^{-1}=\begin{pmatrix}
    a & b \\
    0 & 0
    \end{pmatrix}
    \begin{pmatrix}
    c & d \\
    e & f
    \end{pmatrix} =
    \begin{pmatrix}
    ? & ? \\
    0 & 0
    \end{pmatrix} \not= I_2$

  • A가 n차 정방행렬일때 다음은 서로 동치다.
    • A는 정칙행렬이다.
    • A와 I_n은 행상등하다.
    • A는 유한개의 n차 기본행렬의 곱이다.

 

 

역행렬 구하는 방법

정방행렬 $A$의 역행렬을 구할 때는 $A$ 옆에 단위행렬 $I_n$을 붙인 확대행렬을 만들어 시작한다.

 

$(A \mid I_n)= \left(
\begin{array}{cc|cc}
a & b & 1 & 0 \\
c & d & 0 & 1
\end{array}
\right)$

 

그다음 기본행연산을 이용하여, 왼쪽의 $A$를 단위행렬 $I_n$으로 바꾼다.

$(A \mid I_n)
\rightarrow
(I_n \mid C)$

 

이때 오른쪽에 남은 행렬 $C$가 바로 $A$의 역행렬이 된다.

$C = A^{-1}$

 

즉, 정리해보면 아래와 같다.

$(A \mid I_n)
\rightarrow
(I_n \mid A^{-1})$

 

해당 방법이 가능한 이유

우선 위에서 말했듯이, 행렬에 기본행연산을 적용하는 것은 기본행렬을 왼쪽에서 곱하는 것과 같다
행렬 A를 I_n으로 바꾸기 위해 k번 기본행연산을 수행한 것은 아래와 같다.

$E_k\dotsb E_2E_1A=I_n$

 

여기서 $E_k\dotsb E_2E_1$부분을 결합하여 하나의 행렬 $E$라고 정의한다면 아래와 같다.

$EA = I_n$

 

여기서 역행렬의 정의따라 어떤 행렬 A의 왼쪽에 곱하여 단위행렬 I_n을 만드는 행렬은 역행렬이므로,

$E=A^{-1}$임이 자명하다!

확대행렬에 적용

처음에 만들었던 확대행렬에서 A를 단위행렬로 만들기 위해 연산 행렬 E를 왼쪽에 곱하면 아래와 같은 식이 도출된다.

$E(A\mid I_n) = (EA\mid EI_n)=(I_n\mid E)$

 

여기서 E는 위에서 설명했듯이 A의 역행렬이 되기 때문에 결국,

$E(A\mid I_n)=(I_n\mid A^{-1})$이 된다.

'컴퓨터 공학 > 선형대수학' 카테고리의 다른 글

04. 역행렬(3)  (0) 2026.07.08
04. 역행렬(1)  (0) 2026.06.24
03. 행렬의 연산  (0) 2026.06.23
02. 연립방정식과 행렬  (0) 2026.06.22
01. 일차방정식  (0) 2026.06.18

기본 개념

확률에서 가장 먼저 알아야 하는 개념 네 개가 있다.

  1. 확률실험 : 결과가 미리 정해지지 않은 실험
  2. 표본공간 : 나올 수 있는 모든 결과의 집합
  3. 사건 : 우리가 관심 있는 결과들의 집합
  4. 상호배반사건 : 동시에 일어날 수 없는 사건

확률실험(Random Experiment)

주사위를 던지기 전에 어떤 숫자가 나올지 모른다.

따라서 "주사위를 던진다" 는 확률실험이다.

 

표본공간(Sample Space)

주사위를 던졌을 때 나올 수 있는 모든 결과를 모아둔 것이다.

$S = \{1,2,3,4,5,6\}$

이것을 표본공간이라고 합니다.

즉, 가능한 모든 결과의 집합이다.

 

사건(Event)

표본공간 전체가 아니라 그 중 일부만 관심 있는 경우다.

예를 들어 "짝수가 나오는가?" 에 관심이 있다면,

$A=\{2,4,6\}$ 가 된다.

 

또는 "3보다 큰 수가 나오는가?" 라면,

$B=\{4,5,6\}$ 가 된다.

 

즉, 사건 = 표본공간의 부분집합 이라고 할 수 있다.

 

상호배반사건(Mutually Exclusive Event)

두 사건이 동시에 발생할 수 없는 경우다.
예를 들어 1이 나오는 사건을 A,

$A=\{1\}$

그리고 2가 나오는 사건을 B,

$B=\{2\}$

라고 가정할때, 주사위를 한 번 던져서는 1과 2가 동시에 나올 수는 없다.

 

그렇기 때문에 $A\cap B = \emptyset$이고, A와 B는 상호배반사건이라고 할 수 있다.

 

상호배반이 아닌 경우

짝수가 나오는 사건을 A,

$A=\{2,4,6\}$

3보다 큰 수가 나오는 사건을 B,

$B=\{4,5,6\}$

라고 가정할때, 주사위를 한번 던져서 A와 B가 모두 동시에 만족할 4와 6이 있다.

 

그렇기 때문에 $A\cap B = \{4,6\}$ 으로 상호배반사건이 아니다.

 

사건의 확률

사건 $A$가 일어날 가능성을 확률이라고 하며, 기호로는 다음과 같이 나타낸다.

$P(A)$

사건이 일어난다는 뜻은, 사건이라는 부분집합에서 하나라도 발생하면 사건이 발생했다고 간주한다.


확률은 항상 0 이상 1 이하의 값을 가진다.

$0 \leq P(A) \leq 1$

확률이 0이면 절대로 일어나지 않는 사건이고, 확률이 1이면 반드시 일어나는 사건이다.

 

예시로 표본공간 $S$는 가능한 모든 결과의 집합이므로 반드시 그 중 하나는 일어난다.

그래서 $P(S)=1$ 이다.

 

반대로 공집합 $\emptyset$은 아무 결과도 포함하지 않으므로 절대로 일어날 수 없다.

$P(\emptyset)=0$

 

$P(A\mid B)$의 형태

$P(A)$가 아닌 $P(A\mid B)$의 형태도 존재한다.

의미로는 부분집합 B에서 부분집합 A가 차지하는 비율이다.

 

이 부분집합 B는 생략이 가능한데, 생략 하게 되면 전체집합 $U$로 간주하게 된다.

그래서 앞에 나왔던 $P(A)$는 사실 $P(A\mid U)$와 같다고 볼 수 있다!

 

상호배반사건의 확률

두 사건 $A$, $B$가 상호배반사건이면 동시에 일어날 수 없다.

즉, $A \cap B = \emptyset$ 이다.

 

이 경우 두 사건 중 하나가 일어날 확률은 각각의 확률을 더해서 구할 수 있다.

$P(A \cup B)=P(A)+P(B)$

 

예를 들어 주사위를 던질 때 2, 4, 6이 나오는 사건을 각각 생각하면, 이 사건들은 동시에 일어날 수 없다.

따라서 짝수가 나오는 사건을 $A$라고 하면,

$A={2,4,6}$ 이고,

$P(A)=P({2})+P({4})+P({6})$ 이다.

 

공정한 주사위라면 각 눈이 나올 확률은 모두 $\frac{1}{6}$이므로,

$P(A)=\frac{1}{6}+\frac{1}{6}+\frac{1}{6}=\frac{3}{6}=\frac{1}{2}$ 이다.

 

같은 확률로 발생하는 경우

표본공간이 유한하고, 각 결과가 같은 확률로 발생한다면 사건 $A$의 확률은 다음과 같이 구할 수 있다.

$P(A)=\frac{|A|}{|S|}$

여기서 $|A|$는 사건 $A$에 포함된 원소의 개수이고, $|S|$는 표본공간의 원소 개수이다.

 

예를 들어 주사위에서 짝수가 나오는 사건은

$A={2,4,6}$ 이다.

 

따라서 $|A|=3,\quad |S|=6$ 이므로,

$P(A)=\frac{|A|}{|S|}=\frac{3}{6}=\frac{1}{2}$ 이다.

단, 이 공식은 모든 결과가 같은 확률로 발생할 때만 사용할 수 있다.

 

여사건의 확률

사건 $A$가 일어나지 않는 사건을 여사건이라고 하며, $A^c$로 나타낸다.

사건 $A$와 여사건 $A^c$를 합치면 전체 표본공간이 된다.

$A \cup A^c = S$

 

따라서 두 확률의 합은 1이라고 할 수 있다!

$P(A)+P(A^c)=1$

즉, $P(A^c)=1-P(A)$ 이다.

 

예를 들어 짝수가 나오는 사건의 확률이 $\frac{1}{2}$라면,

짝수가 나오지 않을 확률도 $P(A^c)=1-\frac{1}{2}=\frac{1}{2}$ 이다.

'AI > 수학' 카테고리의 다른 글

전체 확률의 법칙  (0) 2026.01.30
곱의 법칙  (0) 2026.01.15

행렬에서의 항등원과 역수

일차 방정식 $ax = b$ 에서 $a≠0$에서 세 가지 특성을 확인해볼 수 있다.

  1. 역수를 이용해 해를 구할 수 있다.

  2. $a$의 역원이 존재하여 양변에 역원을 곱하면 해를 구할 수 있다.
    $x = a^{-1}b$

  3. 1은 곱셈의 항등원이다.

  4. 어떤 수든지 1을 곱하면, 원래 수가 그대로 유지되기 때문에 1은 곱셈의 항등원이다.
    $a \cdot 1 = a$

  5. 역수를 곱하면 항등원이 된다.
    $a$에 $a$의 역수 $a^{-1}$를 곱하면 1이 된다.
    $a \cdot a^{-1} = 1 (단, a \ne 0)$

이러한 특성들을 행렬에도 비슷하게 적용해볼 수 있다!

  1. 역행렬을 이용해 행렬방정식을 풀 수 있다.
    행렬방정식 $AX = B$ 에서 행렬 A의 역행렬인 $A^{-1}$이 존재한다면,
    역행렬을 양변에 곱하여 $X = A^{-1}B$ 와 같이$X$를 구할 수 있다.
    $X = A^{-1}B$

  2. 단위행렬은 행렬곱의 항등원이다.
    행렬에서 항등원에 해당하는 역할은 단위행렬이다.
    임의의 n차 정방행렬 $A$에 대해 다음이 성립한다.
    $A\cdot I_n = I_n \cdot A = A$

  3. 역행렬을 곱하면 단위행렬이 된다.
    행렬에서 역수에 해당하는 역할은 역행렬이다.
    임의의 n차 정방행렬 $A$에 대해 다음이 성립한다.
    $AA^{-1} = A^{-1}A = I_n$
    즉, 역수(역행렬)을 곱하면 항등원(단위행렬)이 나오는 것이다.

여기서 주의할 것은 모든 행렬이 역행렬을 가지는 것은 아니다.
역행렬은 무조건 정방행렬에서 존재하며, 그중에서도 특정 조건을 만족하는 행렬에 대해서만 존재한다.

이런 역행렬이 존재하는 행렬이 바로 다음에 나오는 정칙행렬이다.

 

 

정칙행렬(Nonsingular matrix)

$n$차 정방행렬 $A$에 대해 어떤 행렬 $B$가 존재하여 행렬곱을 하였더니, 결과로 단위행렬이 나온다고 가정하자.

$AB = BA = I_n$

이때, $A$를 정칙행렬이라고 한다.
간단하게는 어떤 행렬을 곱하여 단위행렬이 나올 수 있다면 정칙행렬이라고 한다.

 

위에서 알아봤듯이, 어떤 행렬을 곱하여 단위행렬이 나온다는 것은 역행렬을 의미한다.
이때 $B$를 $A$의 역행렬이라고 하며, $B = A^{-1}$으로나타낸다.

 

정칙행렬은 역역산이 가능한 행렬이라는 의미에서 Invertible matrix라고도 불린다.

 

역행렬의 유일성

$A$가 정칙행렬이면 역행렬인 $A^-1$ 은 유일하다.


$A $ 의 역행렬을 $ B $와 $ C $라고 한다면

$AB = BA = I$와 $AC = CA = I$를 만족할 것이다.

그럼 $B = BI = B(AC) = (BA)C = IC = C$ 같은 전개로 증명해볼 수 있다.

정칙행렬의 성질

A와 B가 정칙행렬이면 다음이 성립한다.

  • 역행렬의 역행렬
    $A^{-1}$도 정칙행렬이며 $(A^{-1})^{-1} = A$이다.
    $A^{-1}$ 의 입장에서 보면, 자신과 곱했을 때 단위행렬을 만드는 행렬은 $A$이다.

  • 두 정칙행렬의 곱의 역행렬
    $A$, $B$가 정칙행렬이면 $AB$도 정칙행렬이고, $(AB)^{-1} = B^{-1}A^{-1}$ 이다.
    결합법칙을 이용하여 증명한다.

    $(AB)(B^{-1}A^{-1}) = I_n\\
    A(BB^{-1})A^{-1}=I_n\\AI_nA^{-1} = I_n\\
    AA^{-1} = I_n\\$
  • 스칼라배를한 정칙행렬의 역행렬
    정칙행렬 $A$와 0이 아닌 상수 $c$에서, $cA$는 정칙행렬이며 $(cA)^{-1}= \frac{1}{c}A^{-1}$ 이다.
    $(cA)\Big( \cfrac{1}{c}A^{-1}\Big) = I_n\\
    \Big(c\cfrac{1}{c}\Big)(AA^{-1})=I_n\\
    1I_n=I_n\\$
  • 정칙행렬을 전치한 행렬의 역행렬
    정칙행렬 $A$를 전치하여 만든 정칙행렬 $A^T$도 정칙행렬이며, $(A^T)^{-1}=(A^{-1})^T$이다.

    $AA^{-1} = I_n\\
    (AA^{-1})^T = {I_n}^T\\
    (A^{-1})^TA^T = I_n$또한,
    $A^{-1}A = I_n\\
    (A^{-1}A)^T = {I_n}^T\\
    A^T(A^{-1})^T = I_n$
    즉, $(A^{-1})^T$는 $A^T$의 양쪽 역행렬이고, $(A^T)^{-1} = (A^{-1})^T$ 이라고 할 수 있다.

 

 

2차 정방행렬의 역행렬 구하는 공식

아래와 같은 2차 정방행렬 A와, 그 역행렬이 있다고 가정한다.

 

$A =\begin{pmatrix}a & b \\c & d\end{pmatrix},\ A^{-1} = \begin{pmatrix}x & y \\z & w\end{pmatrix}$

 

두 행렬을 곱하면 단위행렬이 나온다.

 

$AA^{-1} =\begin{pmatrix}a & b \\c & d\end{pmatrix}\begin{pmatrix}x & y \\z & w\end{pmatrix} =\begin{pmatrix} ax+bz & ay+bw \\cx+dz & cy+dw\end{pmatrix} =\begin{pmatrix}1 & 0 \\0 & 1\end{pmatrix}$

 

그럼 아래의 네 가지 식이 나온다.

 

$ax+bz=1\\
cx+dz=0\\
ay+bw=0\\
cy+dw=1$

 

이를 같은 미지수를 기준으로 묶어볼 수 있는데, 그렇게 되면 두 쌍의 연립방정식이 나온다.

 

$\begin{cases}
ax + bz = 1\\
cx + dz = 0
\end{cases}$

$\begin{cases}
ay + bw = 0\\
cy + dw = 1
\end{cases}$

 

이를 소거법을 이용하여 각 미지수의 해를 구하면 다음과 같다.

 

$\bigg(x = \cfrac{d}{ad-bc},\
y = \cfrac{-b}{ad-bc},\
z = \cfrac{-c}{ad-bc}.\
w = \cfrac{a}{ad-bc} \bigg)$

 

여기서 $ad-bc$를 $D$라는 알파벳으로 두어 인수분해하면 최종적으로 다음과 같아진다.

 

$\bigg(x = \cfrac{d}{D},\
y = \cfrac{-b}{D},\
z = \cfrac{-c}{D}.\
w = \cfrac{a}{D} \bigg)$

 

그럼 구한 값을 역행렬에 대입하면 역행렬을 구할 수 있게 된다.

 

$A^{-1} =
\begin{pmatrix}
x & y \\
z & w
\end{pmatrix} =
\begin{pmatrix}
\frac{d}{D} & \frac{-b}{D} \\
\frac{-c}{D} & \frac{a}{D}
\end{pmatrix}=\cfrac{1}{D}
\begin{pmatrix}
d & -b \\
-c & a
\end{pmatrix}$

 

여기서 당연하게도 $D$ 는 0이 되면 안되는데, 왜냐하면 0으로 나눌수가 없기 때문이다.
그래서 $D$가 0이라면 역행렬이 존재하지 않는다라고 할 수 있다.


이렇게 역행렬의 존재를 판별할수 있는 $D$를 행렬식(Determinant)라고 한다.

최종적으로 정리하면, 행렬의 역행렬은 다음과 같다.

 

$\frac{1}{ad-bc}
\begin{pmatrix}
d & -b \\
-c & a
\end{pmatrix} (단,ad-bc \ne 0)$

 

지수가 음수인 행렬의 거듭제곱

이전에 행렬의 거듭제곱에 음이 아닌 정수 r과s에 대해 성립하는 특징이 있다고 했었다.
그때는 역행렬을 배우지 않아 불가능했지만 역행렬을 배운 지금은 가능하다.

 

수학자들이 지수가 음의 정수라면 역행렬을 곱해주는것으로 설정했기 때문이다.
예를들어 아래와 같이 사용할 수 있다.

 

$A^{-1} = \text{A의 역행렬}\\
A^{-2} = (A^{-1})^2 = A^{-1}A^{-1} \\
A^{-3} = (A^{-1})^3 = A^{-1}A^{-1}A^{-1}$

 

주의할 것은 역행렬이 존재해야하기 때문에 행렬 $A$는 정칙행렬이어야만 한다.

'컴퓨터 공학 > 선형대수학' 카테고리의 다른 글

04. 역행렬(3)  (0) 2026.07.08
04. 역행렬(2)  (0) 2026.06.29
03. 행렬의 연산  (0) 2026.06.23
02. 연립방정식과 행렬  (0) 2026.06.22
01. 일차방정식  (0) 2026.06.18

들어가며

포트폴리오 프로젝트로 이전부터 만들어 보고 싶었던 장르인 로그라이트를 개발해 보기로 했다.

 

이전 포트폴리오를 만들 때는 기능 구현을 우선시하다 보니, 결국 나중에는 각 시스템끼리 직접 참조가 많아지고 상태 전환 같은 로직이 여러 Manager와 연결되면서 복잡해지고 각 클래스의 책임이 점점 흐려지는 경험이 있었다.

 

그래서 이번에는 개발에 들어가기 전에, 게임 흐름, 오브젝트 생성, 데이터 같은 런타임 구성요소에 대한 시스템을 어떤 기준으로 어떻게 나누어 관리할 것인지 고민했다.

 

직접 구조를 만들어보는 경험은 이전 프로젝트에서 해보았기 때문에, 다른 프레임 워크들이 게임을 개발하면서 생기는 문제를 어떤 기준으로 나누고, 어떻게 관리를 했는지 참고하여, 내 프로젝트에 적용할 수 있는 기준을 찾고자 여러 프레임워크를 찾아 검토해 보았다.

 

 

Framework 후보

QFramework

QFramework는 Unity와 Godot을 대상으로 하는 시스템 설계 프레임워크이며, 공식 설명에서는 SOLID, DDD, 이벤트 기반, 데이터 기반, 계층 구조, MVC, CQRS, 모듈화, 확장 가능한 구조를 지원한다고 소개되어 있다.

 

BDFramework

BDFramework는 Unity 게임 개발을 위한 워크플로우 프레임워크에 가깝다. 개발부터 배포까지의 워크플로우를 제공하며, hot-fixing, asset management, automated building, editor enhancement에 초점을 둔다고 설명되어 있다.

 

ET Framework

ET Framework의 특징은 Unity3D 클라이언트와 C# 서버를 함께 다루는 프레임워크로 볼 수 있다. 공식 저장소에서도 Unity3D Client And C# Server Framework라고 소개되어 있으며, 최근 ET10 설명에서는 분산 MMO 아키텍처, Actor Runtime, 클라우드 기반 서버 인프라, Hot Reload, 자동화된 게임플레이 테스트 등을 제공한다고 설명되어 있다...

 

Unity Game Framework

UGF는 Unity 기반 게임 프레임워크로, 공식 설명에서는 게임 개발 과정에서 자주 사용되는 모듈을 캡슐화하여 개발 과정을 표준화하고, 개발 속도와 품질을 높이는 것을 목표로 한다고 설명되어 있다. 또한 Config, Data Node, Data Table, Entity, Event, FSM, Object Pool, Procedure, Resource, Scene, UI 등 여러 내장 모듈을 제공한다고 되어있다.

 

 

Framework 선택

이번 프로젝트의 목적은 빠르게 기능만 붙이는 것이 아니라, 이전 프로젝트에서 겪었던 구조 문제를 줄이는 것이다.

각 프레임워크마다 참고할 것이 많고 좋았지만 지금 내게 딱 맞는 프레임워크는 UGF(Unity Game Framework)라고 생각했다.

 

QFramework는 코드 구조와 책임 분리 같은 아키텍처 패턴을 참고하기 좋은 프레임워크라고 느꼈다.
Model, System, Command, Event 같은 단위로 기능을 나누는 방식은 각 클래스의 책임을 정리하는 데 도움이 될 수 있어 보였다.

다만 이번 프로젝트에서 내가 먼저 고민하고 있던 것은 코드 아키텍처 자체보다는, "게임 흐름은 어떻게 나눌지, 적 사망이나 레벨업 같은 이벤트는 어떻게 전달할지" 같은 런타임 요소를 어떻게 분리하고 관리할 것인가에 가까웠기 때문에 우선순위를 낮게 두었다.

 

ET Framework는 서버를 함께 다룰 수 있다는 점이 매력적이었는데, 서버와 클라이언트 구조를 함께 고려해야 하는 온라인 게임이나 MMO 프로젝트라면 네트워크 통신, 서버 로직 분리, 분산 구조 등을 학습하기에 좋은 후보라고 생각했다.
하지만 이번 프로젝트는 싱글 플레이 로그라이트를 먼저 구현하는 것이 목표이기 때문에, 서버 구조와 분산 아키텍처까지 포함하는 것은 다소 무겁다고 생각했다.

 

그래서 남은 두 프레임워크 중에 고민을 했었는데,

BDFramework의 경우, 실제 프로젝트에서 필요한 기능들이 다양하게 포함되어 있었기 때문에 잘 익힌다면 게임 개발에서의 여러 방면으로 도움이 될 것 같았다.

다만 현재 시작하려는 프로젝트는 개발부터 배포까지의 전체 워크플로우를 잡는 단계라기보다는 게임의 핵심 구조를 잡는 게 우선이었기 때문에 목표에 비해 범위가 많이 넓다고 생각했다;

 

BDFramework가 게임의 제작부터 배포까지의 파이프라인(빌드, 에셋 관리 등)에 집중한다면, UGF는 제가 당장 해결하고자 하는 인게임 런타임 시스템의 구조화에 집중하고 있어 현재 목표에 더 적합했다고 생각했다.

게임 흐름은 Procedure, 런타임 오브젝트는 Entity, 시스템 간 통신은 Event, 밸런싱 데이터는 Data Table, 화면 전환은 UI라는 모듈로 나누어볼 수 있다고 되어 있는데, 이런 UGF의 구조는 이전 프로젝트에서 경험했던 문제에 대해 내가 어떤 기준으로 시스템을 나누어야 할지 참고할 수 있는 최소한의 기준처럼 보여 현재 문제에서 가장 알맞은 프레임워크라고 판단했다.

 

 

설치

프로젝트의 경로에서 UGF을 clone 해준다.

cd /d E:\Project_Unity\Project_RogueLite\Packages
git clone https://github.com/EllanJiang/UnityGameFramework.git com.jiangyin.gameframework

 

그 후 UGF의 폴더의 package.json에서 version을 2021.05.31에서 2021.5.31로 변경해 준다 

이는 UnityGameFramework 원본 package.json의 version 값이 SemVer 규칙을 벗어나있기 때문에 고쳐주기 위함이다.

 

오류 수정

UGF 코드가 오래된 Unity API를 사용해서 호환성 문제가 생겼다.

아래와 같은 수정을 거쳐 해결한다.

// File
// MyUnityProject\Packages\com.jiangyin.gameframework\Scripts\Editor\ResourceBuilder\ResourceBuilderController.cs

// 수정 전
BuildAssetBundleOptions buildOptions = BuildAssetBundleOptions.DeterministicAssetBundle;
// 수정 후
BuildAssetBundleOptions buildOptions = BuildAssetBundleOptions.None;
// File
// MyUnityProject\Packages\com.jiangyin.gameframework\Scripts\Editor\Misc\ScriptingDefineSymbols.cs


// 수정 전_1
public static string[] GetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup)
{
    return PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(';');
}
// 수정 후_1
public static string[] GetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup)
{
    NamedBuildTarget namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup);
    string defines = PlayerSettings.GetScriptingDefineSymbols(namedBuildTarget);

    return string.IsNullOrEmpty(defines)
        ? new string[0]
        : defines.Split(';');
}


// 수정 전_2
public static void SetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup, string[] scriptingDefineSymbols)
{
    PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Join(";", scriptingDefineSymbols));
}
// 수정 후_2
public static void SetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup, string[] scriptingDefineSymbols)
{
    NamedBuildTarget namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(buildTargetGroup);
    PlayerSettings.SetScriptingDefineSymbols(namedBuildTarget, string.Join(";", scriptingDefineSymbols));
}

 

적용 완료

 

 

UGF 프레임워크 오브젝트

UGF에 prefab이 있는데 해당 prefab을 Scene에 드래그해서 놓으면 사용할 준비가 완료된다.

행렬에 관한 개념

  • 정방행렬 (Square matrix)
    행과 열의 개수가 같은 행렬이다.
    아래 행렬은 $2\times 2$ 행렬로 정방행렬이다.

    $A =\begin{pmatrix}1 & 2 \\3 & 4\end{pmatrix}$

  • 주대각원소
    정방행렬일 때, $a_{ii}(1\le i \le n)$를 주대각원소라고 한다.

    $\begin{pmatrix}
    a_{11} & a_{12} & a_{13} \\
    a_{21} & a_{22} & a_{23} \\
    a_{31} & a_{32} & a_{33}
    \end{pmatrix}$

    위 행렬에서 주 대각 원소는 $\{a_{11},\ a_{22},\ a_{33}\}$이다.

  • 대각행렬 (Diagonal matrix)
    주대각원소를 제외한 모든 원소가 0인 정방행렬이다.
    $a_{ij} = 0\ (단, i≠j)$

    $\begin{pmatrix}
    2 & 0 & 0 \\
    0 & -1 & 0 \\
    0 & 0 & 5
    \end{pmatrix}$

    위 행렬처럼 주대각원소의 값이 무엇이든 주대각선 밖의 원소가 모두 0이기만 하면 된다.

  • 스칼라행렬 (Scalar matrix)
    대각행렬에서 주 대각 원소가 모두 같은 행렬
    $a_{ii} = c\ (1\le i \le n)$

  • 단위행렬 (Identity matrix)
    스칼라행렬에서 주대각원소가 모두 1인 행렬
    $a_{ii} = 1\ (1\le i \le n)$
  • 삼각행렬
    정방행렬 중에서 한쪽 삼각형 부분의 원소가 모두 0인 행렬이다.
    두 가지 종류로 나뉜다.
    • 하삼각행렬 (Lower triangular matrix)
      $a_{ij} = 0\ (단, i < j)$

      $\begin{pmatrix}
      1 & 0 & 0 \\
      2 & 3 & 0 \\
      4 & 5 & 6
      \end{pmatrix}$

    • 상삼각행렬 (Upper triangular matrix)
      $a_{ij} = 0\ (단, i > j)$

      $\begin{pmatrix}
      1 & 2 & 3 \\
      0 & 4 & 5 \\
      0 & 0 & 6
      \end{pmatrix}$

 

행렬의 합

두 행렬의 합은 두 행렬의 크기가 같을 때만 정의된다.
예를 들어 두 행렬 $A, B$가 모두 $m \times n$ 행렬이면 $A+B$를 계산할 수 있다.

$A = \begin{pmatrix}1 & 2 \\3 & 4\end{pmatrix},\quad B =\begin{pmatrix}5 & 6 \\7 & 8\end{pmatrix}$

이때 행렬의 합은 같은 위치에 있는 원소끼리 더한다.

$\begin{pmatrix}
6 & 8 \\
10 & 12
\end{pmatrix}$

 

성질

  • 교환법칙 성립
    $A+B = B+A$

  • 결합법칙 성립
    $(A+B)+C = A+(B+C)$

  • 항등원 존재
    행렬의 덧셈에서 항등원은 영행렬이다.
    $A + O = A$ 
    이때 영행렬 $O$도 반드시 $A$와 같은 크기여야 한다.

  • 역원 존재
    행렬 $A$에 대해 덧셈의 역원은 $-A$이다

 

행렬의 스칼라 곱

행렬의 스칼라곱은 행렬의 모든 원소에 같은 스칼라를 곱하는 연산이다

$A =\begin{pmatrix}1 & 2 \\3 & 4\end{pmatrix}$

에서 $3A$는 다음과 같다.

$3A = \begin{pmatrix}3 & 6 \\9 & 12\end{pmatrix}$

 

성질

  • $(c+d)A = cA + dA$
  • $c(A+B) = cA + cB$
  • $c(dA) = (cd)A$
  • $1A = A$

 

행렬의 곱(Product)

행렬 $A$가 $m \times p$행렬이고, 행렬 $B$가 $p \times n$ 행렬일 때, 곱 $AB$를 정의할 수 있다.
즉, 앞 행렬의 열 개수와, 뒤 행렬의 행 개수가 같아야 한다.

행렬의 곱은 아래와 같이 정의된다.
 $c_{ij} = \sum\limits_{k=1}^{p}a_{ik}b_{kj}\ (1\le i \le m, 1\le j\le n)$로 정의 된다.
이를 간단하게 $AB = C$ 로 표현한다.

아래 두 행렬이 있다고 가정한다.

$A =\begin{pmatrix}1 & 2 \\3 & 4\end{pmatrix}, \quad B =\begin{pmatrix} 5 & 6 \\7 & 8\end{pmatrix}$

이때, $AB$는 다음과 같다.

$AB =\begin{pmatrix}1\cdot5 + 2\cdot7 & 1\cdot6 + 2\cdot8 \\3\cdot5 + 4\cdot7 & 3\cdot6 + \cdot8\end{pmatrix} = \begin{pmatrix}19 & 22 \\43 & 50\end{pmatrix}$

 

행렬들의 선형결합

같은 크기의 행렬들은 벡터처럼 다룰 수 있고, 같은 크기의 행렬들의 집합은 벡터공간이 된다.

예를 들어 모든 $2 \times 2$ 행렬들의 집합은 다음과 같다.

$M_{2 \times 2}=\left\{\begin{pmatrix}a & b \\c & d\end{pmatrix}\mid a,b,c,d \in \mathbb{R}\right\}$

이 집합 안의 행렬들은 서로 더할 수 있고, 스칼라배할 수 있다, 그리고 그 결과 또한 여전히 $2 \times 2$ 행렬이다.
그래서 행렬도 벡터처럼 다음과 같은 계산이 가능하다.

$c1A1+c2A2+c3A3$

이런 식을 행렬들의 선형결합(linear combination)이라고 한다.

 

성질

  • 교환 법칙 불성립
    행렬곱은 일반적으로 교환법칙이 성립하지 않지만, 특수하게 가능한 경우가 한 가지 있다.
    우선 교환법칙을 적용했을 때의 경우가 네 가지를 알아본다.
    행렬$m\times p$행렬인 A와 $p\times n$행렬인 B의 곱인 AB에서 교환법칙을 적용했다고 가정한다.

    • BA가 정의되지 않는 경우(n ≠ m인 경우)
      행렬곱 자체를 수행할 수 없다.
    • BA는 정의되지만, AB의 결과와 크기가 다른 경우
      행렬곱은 가능하나 기존 AB의 크기가 다르기에 상등하지 않다.
    • BA가 정의되고 AB와 크기도 같지만  AB ≠ BA인 경우

      $A =\begin{pmatrix}1 & 2 \\0 & 1\end{pmatrix},B =\begin{pmatrix}1 & 0 \\3 & 1\end{pmatrix}$

      위의 두 행렬이 있다면 각 행렬곱은 아래와 같다.

      $AB =\begin{pmatrix}7 & 2 \\3 & 1\end{pmatrix}, BA =\begin{pmatrix}1 & 2 \\3 & 7\end{pmatrix}$

      각 결과의 행렬은 서로 상등하지 않다.
          
    • BA가 정의되고 AB와 크기도 같고 AB = BA인 경우
      같은 크기의 단위행렬은 해당 조건을 만족한다.   
      $AI = IA = A$
          
      스칼라 행렬 $cI$도 같은 크기의 행렬 $A$와 곱할 때 순서를 바꾸어도 결과가 같다.
      $A(cI) = (cI)A = cA$
          
      또한 대각행렬끼리의 곱에서도 종종 같은 경우가 생긴다.
      (모든 경우가 성립하지는 않음!)
  • 결합법칙 성립
    $(AB)C = A(BC)$
    스칼라배를 포함한 결합법칙도 성립한다.
    $c(AB) = (cA)B = A(cB)$

  • 분배법칙도 성립
    $A(B+C) = AB + AC$
    $(A+B)C = AC + BC$

  • 항등원
    행렬곱의 항등원은 단위행열이다.
    정방행렬 `$A$`에 대해 다음이 성립한다.
    $AI = IA = A$

    하지만 $A$가 $m \times n$ 행렬이라면 왼쪽에 곱하는 단위행렬과 오른쪽에 곱하는 단위행렬의 크기가 다르다.   
    $I_mA = A$
    $AI_n = A$
    따라서 행렬곱에서는 단위행렬의 크기를 반드시 확인해야 한다.
  •  

'컴퓨터 공학 > 선형대수학' 카테고리의 다른 글

04. 역행렬(3)  (0) 2026.07.08
04. 역행렬(2)  (0) 2026.06.29
04. 역행렬(1)  (0) 2026.06.24
02. 연립방정식과 행렬  (0) 2026.06.22
01. 일차방정식  (0) 2026.06.18

+ Recent posts