[TIL] C# - ์•Œ๊ณ ๋ฆฌ์ฆ˜ - day 28

๋ญ‰ํฌ์˜ ๊ฐœ๋ฐœยท2023๋…„ 8์›” 26์ผ
0

C# - Camp

๋ชฉ๋ก ๋ณด๊ธฐ
12/18
post-thumbnail

๐Ÿง ๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ

์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ฐฐ์šฐ๊ธฐ ์ „, ์ฝ”๋“œ ์นดํƒ€๋ฅผ ํ†ตํ•ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ง›๋ดค๋Š”๋ฐ,

๋ฐฐ์šฐ๊ณ  ๋‚œ ํ›„ ์กฐ๊ธˆ ๋” ์ดํ•ด๊ฐ€ ์ž˜๋œ๋‹ค!


๐Ÿง ์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ

  • ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ธฐ์ดˆ

  • ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๊ณ ๊ธ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๋ฌธ์ œ ํ•ด๊ฒฐ ์ „๋žต๊ณผ ์‹ค์ „ ์—ฐ์Šต

  • ์—ผ์˜ˆ์ฐฌ ํŠœํ„ฐ๋‹˜


๐Ÿง ๊ธฐ์–ตํ•  ๊ฒƒ

์•Œ๊ณ ๋ฆฌ์ฆ˜

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋‹จ๊ณ„์ ์ธ ๋ฐฉ๋ฒ•

  • ์ž…๋ ฅ์„ ๋ฐ›์•„ ์›ํ•˜๋Š” ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ ˆ์ฐจ.

์ค‘์š”์„ฑ

  1. ํšจ์œจ์  ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๋งค์šฐ ์ค‘์š”.

  2. ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋‘ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘, ํšจ์œจ์  ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์‹œ๊ฐ„, ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ์ด ์ข‹๋‹ค.


Big O

์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํšจ์œจ์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ‘œ๊ธฐ๋ฒ•.

  • ์ž…๋ ฅ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์‹œ๊ฐ„์ด๋‚˜ ๊ณต๊ฐ„์„ ํ•„์š”๋กœ ํ•˜๋Š”์ง€ ์„ค๋ช….

  • ์ตœ์•…์˜ ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ ค!

  • ํ‘œ๊ธฐ๋ฒ• ๊ณ„์‚ฐ

  1. ์ƒ์ˆ˜ ๋ฒ„๋ฆฌ๊ธฐ
    ์‹œ๊ฐ„ ๋ณต์žก๋„์—์„œ ๊ฐ€์žฅ ํฐ ์˜ํ–ฅ์„ ์ฃผ๋Š” ํ•ญ๋ชฉ์„ ์ค‘์‹ฌ์œผ๋กœ ์ฒดํฌ.
    ์ƒ์ˆ˜ ํ•ญ๋ชฉ์ด๋‚˜, ๋‚ฎ์€ ์ฐจ์ˆ˜์˜ ํ•ญ๋ชฉ์€ ๋ฒ„๋ฆผ.
    e.g.,
    O(2n), O(3n^2) -> O(n), O(n^2)

  2. ์ตœ๊ณ  ์ฐจ์ˆ˜ ํ•ญ๋ชฉ๋งŒ ๋‚จ๊ธฐ๊ธฐ
    ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ํ•ญ๋ชฉ์— ์ดˆ์ .
    ๊ฐ€์žฅ ํฐ ์ฐจ์ˆ˜์˜ ํ•ญ๋ชฉ์„ ๋‚จ๊ธฐ๊ณ , ๋‚˜๋จธ์ง€๋Š” ๋ฒ„๋ฆฐ๋‹ค.
    e.g.,
    O(n^2 + n) -> O(n^2)

  3. ๋‹คํ•ญ์‹์˜ ๊ฒฝ์šฐ ์ตœ๊ณ  ์ฐจ์ˆ˜ ํ•ญ๋ชฉ๋งŒ ๊ณ ๋ ค
    ๋‹คํ•ญ์‹์˜ ๊ฒฝ์šฐ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š” ํ•ญ๋ชฉ์— ์ดˆ์ .
    ์ƒ์ˆ˜ํ•ญ, ๋‚ฎ์€ ์ฐจ์ˆ˜์˜ ํ•ญ๋ชฉ์€ ๋ฌด์‹œ.
    e.g.,
    O(3n^3 + 5n^2 + 2n + 7) -> O(n^3)

  4. ์—ฐ์‚ฐ์ž ์ƒ์ˆ˜ ๋ฌด์‹œ
    ์—ฐ์‚ฐ์ž, ์ƒ์ˆ˜ ๊ฐ’ ๋ฌด์‹œ.
    e.g.,
    O(3n^2 + 4n +2) -> O(n^2)

O(1)

  • ์ƒ์ˆ˜ ์‹œ๊ฐ„, ์ž…๋ ฅ ํฌ๊ธฐ์— ์ƒ๊ด€์—†์ด ํ•ญ์ƒ ์ผ์ • ์‹œ๊ฐ„ ์†Œ์š”.

O(n)

  • ์„ ํ˜• ์‹œ๊ฐ„, ์ž…๋ ฅ ํฌ๊ธฐ์— ๋น„๋ก€ํ•˜์—ฌ ์‹œ๊ฐ„ ์†Œ์š”.

O(n^2)

  • ์ด์ฐจ ์‹œ๊ฐ„, ์ž…๋ ฅ ํฌ๊ธฐ์˜ ์ œ๊ณฑ์— ๋น„๋ก€ํ•˜์—ฌ ์‹œ๊ฐ„ ์†Œ์š”.

O(log n)

  • ๋กœ๊ทธ ์‹œ๊ฐ„, ์ž…๋ ฅ ํฌ๊ธฐ์˜ ๋กœ๊ทธ์— ๋น„๋ก€ํ•˜์—ฌ ์‹œ๊ฐ„ ์†Œ์š”.

์‹œ๊ฐ„ ๋ณต์žก๋„ (Time Complexity)

์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„.

  • ์‹ค์ œ ์‹œ๊ฐ„์ด ์•„๋‹Œ, ์ž…๋ ฅ ํฌ๊ธฐ์— ๋Œ€ํ•œ ์—ฐ์‚ฐ ํšŸ์ˆ˜

  • Big - O ํ‘œ๊ธฐ๋ฒ• ์‚ฌ์šฉํ•˜์—ฌ ํ‘œ์‹œ.

e.g.,

int sum(int n)
{
	int sum = 0;
	for (int i= 0; i < n; i++)
	{
		sum += i;
	}
	return sum;
}

for ๋ฃจํ”„๊ฐ€ i = 0 ๋ถ€ํ„ฐ ์ž…๋ ฅ๊ฐ’ n ๊นŒ์ง€ ์ˆœํšŒ๋ฅผ ๋Œ๋ฉฐ, sum์— i ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹.
์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(n) -> n์ด๋ผ๋Š” ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„์„œ, n๋งŒํผ ๋ฐ˜๋ณตํ•˜๊ธฐ ๋•Œ๋ฌธ.

e.g.,

void PrintPairs(int n)
{
	for(int i= 0; i <= n; i++)
	{
		for (int j = 0; j <= n; j++)
		{
			Console.WriteLine(i + ", " + j);
		}
	}
}

for ๋ฃจํ”„๊ฐ€ ๋‘ ๊ฐœ ์ค‘์ฒฉ. ๊ฐ ๋ฃจํ”„๋Š” 0๋ถ€ํ„ฐ n๊นŒ์ง€ ์ˆœํšŒ,
์ „์ฒด ์—ฐ์‚ฐ ํšŸ์ˆ˜๋Š” n^2, ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(n^2)

e.g.,

int Fibonacci(int n)
{
	if (n <= 1)
	{
		return n;
	else
	{
		return Fibonacci(n - 1) + (n - 2);
 	}
}

์žฌ๊ท€์ ์œผ๋กœ ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด ๊ณ„์‚ฐ. ๊ฐ ํ˜ธ์ถœ๋งˆ๋‹ค ๋‘ ๋ฒˆ์˜ ์žฌ๊ท€ ํ˜ธ์ถœ ์ˆ˜ํ–‰
-> ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(2^n)
๋งค์šฐ ๋น„ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•.


๊ณต๊ฐ„ ๋ณต์žก๋„ (Space Complexity)

์ฝ”๋“œ์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์‹ค์ œ ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ(๋ฐ”์ดํŠธ)๋กœ ์ธก์ •ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ,
์ž…๋ ฅ ํฌ๊ธฐ์— ๋”ฐ๋ผ ํ•„์š”ํ•œ ์ €์žฅ ๊ณต๊ฐ„์˜ ์–‘์„ ์ธก์ •ํ•˜๋Š” ์ด์œ ๋ฅผ ์„ค๋ช….

e.g.,

// ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n)
int FindMax(int[] arr)
{
    int max = arr[0];

    for (int i = 1; i < arr.Length; i++)
    {
        if (arr[i] > max)
        {
            max = arr[i];
        }
    }

    return max;
}

// ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n^2)
int FindMax2(int[] arr)
{
    for (int i = 0; i < arr.Length; i++)
    {
        bool isMax = true;
		
        for (int j = 0; j < arr.Length; j++)
        {
            if (arr[j] > arr[i])
            {
                isMax = false;
                break;
            }
        }

        if (isMax)
        {
            return arr[i];
        }
    }

    return -1;
}

int[] arr = new int[] { 1, 2, 3, 4, 5 };

// FindMax ๋ฉ”์„œ๋“œ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n), ๊ณต๊ฐ„ ๋ณต์žก๋„: O(1)
int max = FindMax(arr);

// ๋ฐฐ์—ด์˜ ํฌ๊ธฐ์— ๋น„๋ก€ํ•˜์—ฌ ์‹คํ–‰ ์‹œ๊ฐ„์ด ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ O(n)์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค. 
// ๋˜ํ•œ ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ณต๊ฐ„ ๋ณต์žก๋„๋Š” O(1)์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

// FindMax2 ๋ฉ”์„œ๋“œ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n^2), ๊ณต๊ฐ„ ๋ณต์žก๋„: O(1)
int max2 = FindMax2(arr);

// ์ด์ค‘ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฐ์—ด์˜ ํฌ๊ธฐ์— ์ œ๊ณฑ์— ๋น„๋ก€ํ•˜์—ฌ ์‹คํ–‰ ์‹œ๊ฐ„์ด ์ฆ๊ฐ€ํ•˜๋ฏ€๋กœ O(n^2)์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค. 
// ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ณต๊ฐ„ ๋ณต์žก๋„๋Š” O(1)์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‘˜ ๋‹ค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ทธ๋Œ€๋กœ ์“ฐ๊ธฐ ๋•Œ๋ฌธ! (๋ฐ›์•„์˜จ ๋ฐฐ์—ด์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ.)

e.g.,

public static int[] RemoveDuplicates(int[] array)
{
    List<int> distinctList = new List<int>();

    foreach (int num in array)
    {
        if (!distinctList.Contains(num))
        {
            distinctList.Add(num);
        }
    }

    return distinctList.ToArray();
}

์‹œ๊ฐ„ ๋ณต์žก๋„ O(n), ๊ณต๊ฐ„ ๋ณต์žก๋„ O(n)


์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ํŠน์ • ์ˆœ์„œ๋กœ ๋ฐฐ์—ดํ•˜๋Š” ๋ฐฉ๋ฒ•

์„ ํƒ ์ •๋ ฌ (Selection Sort)

  • ๋ฐฐ์—ด์—์„œ ์ตœ์†Œ๊ฐ’(์ตœ๋Œ€๊ฐ’)์„ ์ฐพ์•„ ๋งจ ์•ž(๋งจ ๋’ค)์™€ ๊ตํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•.

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•…์˜ ๊ฒฝ์šฐ, ํ‰๊ท ์  ๊ฒฝ์šฐ = O(n^2)

  • ๊ณต๊ฐ„ ๋ณต์žก๋„ : O(1) (์ƒ์ˆ˜ ํฌ๊ธฐ์˜ ์ถ”๊ฐ€ ๊ณต๊ฐ„์ด ํ•„์š”ํ•˜์ง€ ์•Š์Œ.)

int[] arr = new int[] { 5, 2, 4, 6, 1, 3 };

for (int i = 0; i < arr.Length - 1; i++)
{
    int minIndex = i;

    for (int j = i + 1; j < arr.Length; j++)
    {
        if (arr[j] < arr[minIndex])
        {
            minIndex = j;
        }
    }

    int temp = arr[i];
    arr[i] = arr[minIndex];
    arr[minIndex] = temp;
}

foreach (int num in arr)
{
    Console.Write(num);
}

123456

์‚ฝ์ž… ์ •๋ ฌ (Insert Sort)

  • ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„์—์„œ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์™€ ์ •๋ ฌ๋œ ๋ถ€๋ถ„์— ์ ์ ˆํ•œ ์œ„์น˜์— ์‚ฝ์ž….

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(n^2), ์ •๋ ฌ = O(n)

  • ๊ณต๊ฐ„ ๋ณต์žก๋„ : O(1) (์ƒ์ˆ˜ ํฌ๊ธฐ์˜ ์ถ”๊ฐ€ ๊ณต๊ฐ„์ด ํ•„์š”ํ•˜์ง€ ์•Š์Œ.)

int[] arr = new int[] { 5, 2, 4, 6, 1, 3 };

for (int i = 1; i < arr.Length; i++)
{
    int j = i - 1;
    int key = arr[i];

    while (j >= 0 && arr[j] > key)
    {
        arr[j + 1] = arr[j];
        j--;
    }

    arr[j + 1] = key;
}

foreach (int num in arr)
{
    Console.WriteLine(num);
}

ํ€ต ์ •๋ ฌ (Quick Sort)

  • ํ”ผ๋ฒ—์„ ๊ธฐ์ค€์œผ๋กœ ์ž‘์€ ์š”์†Œ๋Š” ์™ผ์ชฝ, ํฐ ์š”์†Œ๋Š” ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๋ถ„ํ• , ์žฌ๊ท€์  ์ •๋ ฌ.
  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(n^2), ์ •๋ ฌ = O(n log n)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(n), ํ‰๊ท  = O(log n) (์žฌ๊ท€ ํ˜ธ์ถœ์— ํ•„์š”ํ•œ ์Šคํƒ ๊ณต๊ฐ„)
void QuickSort(int[] arr, int left, int right)
{
    if (left < right)
    {
        int pivot = Partition(arr, left, right);

        QuickSort(arr, left, pivot - 1);
        QuickSort(arr, pivot + 1, right);
    }
}

int Partition(int[] arr, int left, int right)
{
    int pivot = arr[right];
    int i = left - 1;
	// left์— ์žˆ๋Š” ๊ฐ’์ด i๋ณด๋‹ค ์ž‘์œผ๋ฉด,
    for (int j = left; j < right; j++)
    {
        if (arr[j] < pivot)
        {
            i++;
            Swap(arr, i, j);
        }
    }

    Swap(arr, i + 1, right);

    return i + 1;
}

void Swap(int[] arr, int i, int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

int[] arr = new int[] { 5, 2, 4, 6, 1, 3 };

QuickSort(arr, 0, arr.Length - 1);

foreach (int num in arr)
{
    Console.WriteLine(num);
}

๋ณ‘ํ•ฉ ์ •๋ ฌ (Merge Sort)

  • ๋ฐฐ์—ด์„ ๋ฐ˜์œผ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ๋ถ€๋ถ„์„ ์žฌ๊ท€์ ์œผ๋กœ ์ •๋ ฌ, ๋ณ‘ํ•ฉ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ๋ชจ๋“  ๊ฒฝ์šฐ = O(n log n)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„ : O(n) (์ •๋ ฌ์„ ์œ„ํ•œ ์ž„์‹œ ๋ฐฐ์—ด ํ•„์š”)
void MergeSort(int[] arr, int left, int right)
{
    if (left < right)
    {
        int mid = (left + right) / 2;

        MergeSort(arr, left, mid);
        MergeSort(arr, mid + 1, right);
        Merge(arr, left, mid, right);
    }
}

void Merge(int[] arr, int left, int mid, int right)
{
    int[] temp = new int[arr.Length];

    int i = left;
    int j = mid + 1;
    int k = left;

    while (i <= mid && j <= right)
    {
        if (arr[i] <= arr[j])
        {
            temp[k++] = arr[i++];
        }
        else
        {
            temp[k++] = arr[j++];
        }
    }

    while (i <= mid)
    {
        temp[k++] = arr[i++];
    }

    while (j <= right)
    {
        temp[k++] = arr[j++];
    }

    for (int l = left; l <= right; l++)
    {
        arr[l] = temp[l];
    }
}

int[] arr = new int[] { 5, 2, 4, 6, 1, 3 };

MergeSort(arr, 0, arr.Length - 1);

foreach (int num in arr)
{
    Console.WriteLine(num);
}

Sort

๋ฐฐ์—ด์ด๋‚˜ ๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ๋“ค์„ ์ •๋ ฌํ•˜๋Š” ๋ฉ”์„œ๋“œ.

  • ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ˆ˜ํ–‰, ์ž๋ฃŒํ˜•์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ์ •๋ ฌ ๊ธฐ์ค€์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์›๋ž˜์˜ ๋ฐฐ์—ด์ด๋‚˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ฏ€๋กœ, ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋‹ค.

// ์ •์ˆ˜ ๋ฐฐ์—ด ์ •๋ ฌ ์˜ˆ์ œ
int[] numbers = { 5, 2, 8, 3, 1, 9, 4, 6, 7 };
Array.Sort(numbers);
Console.WriteLine(string.Join(", ", numbers));

// ๋ฌธ์ž์—ด ๋ฆฌ์ŠคํŠธ ์ •๋ ฌ ์˜ˆ์ œ
List<string> names = new List<string> { "John", "Alice", "Bob", "Eve", "David" };
names.Sort();
Console.WriteLine(string.Join(", ", names));

ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์—์„œ ํŠน์ • ํ•ญ๋ชฉ์„ ์ฐพ๋Š” ๋ฐฉ๋ฒ• ์ œ๊ณต.

๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ์ฐจ๋ก€๋Œ€๋กœ ๊ฒ€์‚ฌ, ์›ํ•˜๋Š” ํ•ญ๋ชฉ ์ฐพ์Œ. (์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋น„๊ต, ๋ฐฐ์—ด ์ •๋ ฌ X)

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(n)
int SequentialSearch(int[] arr, int target)
{
    for (int i = 0; i < arr.Length; i++)
    {
        if (arr[i] == target)
        {
            return i;
        }
    }

    return -1;
}

์ •๋ ฌ๋œ ๋ฐฐ์—ด์—์„œ ๋น ๋ฅด๊ฒŒ ์›ํ•˜๋Š” ํ•ญ๋ชฉ ์ฐพ๋Š” ๋ฐฉ๋ฒ•. (๋ฐฐ์—ด์ด ์ •๋ ฌ๋˜๋ฉด ์‚ฌ์šฉ!)

  • ์ค‘๊ฐ„ ์š”์†Œ์™€ ์ฐพ๋Š” ํ•ญ๋ชฉ ๋น„๊ต, ๋น„๊ต ๋Œ€์ƒ์ด ์ž‘์œผ๋ฉด ์™ผ์ชฝ, ํฌ๋ฉด ์˜ค๋ฅธ์ชฝ ํƒ์ƒ‰

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(log n)

int BinarySearch(int[] arr, int target)
{
    int left = 0;
    int right = arr.Length - 1;

    while (left <= right)
    {
        int mid = (left + right) / 2;

        if (arr[mid] == target)
        {
            return mid;
        }
        else if (arr[mid] < target)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
        }
    }

    return -1;
}


๊ทธ๋ž˜ํ”„ (Graph)

์ •์ (Vertex) ๊ฐ„์„  (Edge) ๋กœ ์ด๋ฃจ์–ด์ง„ ์ž๋ฃŒ ๊ตฌ์กฐ

  • ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„(Directed Graph), ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„(Undirected Graph)

  • ๊ฐ€์ค‘์น˜ ๊ทธ๋ž˜ํ”„(Weighted Graph) ๊ฐ„์„ ์— ๊ฐ€์ค‘์น˜ ์žˆ์Œ.

๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰ (Depth-First Search, DFS)

ํŠธ๋ฆฌ๋‚˜ ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰. ๋ฃจํŠธ์—์„œ ์‹œ์ž‘, ๊ฐ€๋Šฅํ•œ ๊นŠ์ด ๋“ค์–ด๊ฐ€ ๋…ธํŠธ๋ฅผ ํƒ์ƒ‰, ๋” ์ด์ƒ ๋ฐฉ๋ฌธํ•  ๋…ธ๋“œ๊ฐ€ ์—†์œผ๋ฉด ์ด์ „ ๋…ธ๋“œ๋กœ ๋Œ์•„๊ฐ„๋‹ค.

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(V+E) (V = ๋…ธ๋“œ, E = ๊ฐ„์„ )

๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰ (Breadth - First Search, BFS)

ํŠธ๋ฆฌ๋‚˜ ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ์ƒ‰. ๋ฃจํŠธ์—์„œ ์‹œ์ž‘, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋…ธํŠธ๋ถ€ํ„ฐ ๋ฐฉ๋ฌธ ํ›„ ๋‹ค์Œ ๋ ˆ๋ฒจ ๋…ธ๋“œ ๋ฐฉ๋ฌธ.

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ : ์ตœ์•… = O(V+E) (V = ๋…ธ๋“œ, E = ๊ฐ„์„ )
using System;
using System.Collections.Generic;

public class Graph
{
    private int V; // ๊ทธ๋ž˜ํ”„์˜ ์ •์  ๊ฐœ์ˆ˜
    private List<int>[] adj; // ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ

    public Graph(int v)
    {
        V = v;
        adj = new List<int>[V];
        for (int i = 0; i < V; i++)
        {
            adj[i] = new List<int>();
        }
    }

    public void AddEdge(int v, int w)
    {
        adj[v].Add(w);
    }

    public void DFS(int v)
    {
        bool[] visited = new bool[V];
        DFSUtil(v, visited);
    }

    private void DFSUtil(int v, bool[] visited)
    {
        visited[v] = true;
        Console.Write($"{v} ");

        foreach (int n in adj[v])
        {
            if (!visited[n])
            {
                DFSUtil(n, visited);
            }
        }
    }

    public void BFS(int v)
    {
        bool[] visited = new bool[V];
        Queue<int> queue = new Queue<int>();

        visited[v] = true;
        queue.Enqueue(v);

        while (queue.Count > 0)
        {
            int n = queue.Dequeue();
            Console.Write($"{n} ");

            foreach (int m in adj[n])
            {
                if (!visited[m])
                {
                    visited[m] = true;
                    queue.Enqueue(m);
                }
            }
        }
    }
}

public class Program
{
    public static void Main()
    {
        Graph graph = new Graph(6);

        graph.AddEdge(0, 1);
        graph.AddEdge(0, 2);
        graph.AddEdge(1, 3);
        graph.AddEdge(2, 3);
        graph.AddEdge(2, 4);
        graph.AddEdge(3, 4);
        graph.AddEdge(3, 5);
        graph.AddEdge(4, 5);

        Console.WriteLine("DFS traversal:");
        graph.DFS(0);
        Console.WriteLine();

        Console.WriteLine("BFS traversal:");
        graph.BFS(0);
        Console.WriteLine();
    }
}

์ตœ๋‹จ ๊ฒฝ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Shortest Path Problem)

๋‹ค์ต์ŠคํŠธ๋ผ (Dijkstra)

ํ•˜๋‚˜์˜ ์‹œ์ž‘ ์ •์ ์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์ •์ ๊นŒ์ง€ ์ตœ๋‹จ ๊ฒฝ๋กœ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜. ์Œ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ๊ฐ–๋Š” ๊ฐ„์„ ์ด ์—†๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ

using System;

class DijkstraExample
{
    static int V = 6; // ์ •์ ์˜ ์ˆ˜

    // ์ฃผ์–ด์ง„ ๊ทธ๋ž˜ํ”„์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    static void Dijkstra(int[,] graph, int start)
    {
        int[] distance = new int[V]; // ์‹œ์ž‘ ์ •์ ์œผ๋กœ๋ถ€ํ„ฐ์˜ ๊ฑฐ๋ฆฌ ๋ฐฐ์—ด
        bool[] visited = new bool[V]; // ๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ๋ฐฐ์—ด

        // ๊ฑฐ๋ฆฌ ๋ฐฐ์—ด ์ดˆ๊ธฐํ™”
        for (int i = 0; i < V; i++)
        {
            distance[i] = int.MaxValue;
        }

        distance[start] = 0; // ์‹œ์ž‘ ์ •์ ์˜ ๊ฑฐ๋ฆฌ๋Š” 0

        // ๋ชจ๋“  ์ •์ ์„ ๋ฐฉ๋ฌธํ•  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
        for (int count = 0; count < V - 1; count++)
        {
            // ํ˜„์žฌ ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ์ •์ ๋“ค ์ค‘์—์„œ ์ตœ์†Œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง„ ์ •์ ์„ ์ฐพ์Œ
            int minDistance = int.MaxValue;
            int minIndex = -1;

            for (int v = 0; v < V; v++)
            {
                if (!visited[v] && distance[v] <= minDistance)
                {
                    minDistance = distance[v];
                    minIndex = v;
                }
            }

            // ์ตœ์†Œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง„ ์ •์ ์„ ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ
            visited[minIndex] = true;

            // ์ตœ์†Œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง„ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์ ๋“ค์˜ ๊ฑฐ๋ฆฌ ์—…๋ฐ์ดํŠธ
            for (int v = 0; v < V; v++)
            {
                if (!visited[v] && graph[minIndex, v] != 0 && distance[minIndex] != int.MaxValue && distance[minIndex] + graph[minIndex, v] < distance[v])
                {
                    distance[v] = distance[minIndex] + graph[minIndex, v];
                }
            }
        }

        // ์ตœ๋‹จ ๊ฒฝ๋กœ ์ถœ๋ ฅ
        Console.WriteLine("์ •์ \t๊ฑฐ๋ฆฌ");
        for (int i = 0; i < V; i++)
        {
            Console.WriteLine($"{i}\t{distance[i]}");
        }
    }

    static void Main(string[] args)
    {
        int[,] graph = {
            { 0, 4, 0, 0, 0, 0 },
            { 4, 0, 8, 0, 0, 0 },
            { 0, 8, 0, 7, 0, 4 },
            { 0, 0, 7, 0, 9, 14 },
            { 0, 0, 0, 9, 0, 10 },
            { 0, 0, 4, 14, 10, 0 }
        };

        int start = 0; // ์‹œ์ž‘ ์ •์ 

        Dijkstra(graph, start);
    }
}

๋ฒจ๋งŒ - ํฌ๋“œ(Bellman - Ford)

์Œ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ๊ฐ–๋Š” ๊ฐ„์„ ์ด ์žˆ๋Š” ๊ทธ๋ž˜ํ”„์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ. ์Œ์ˆ˜ ์‚ฌ์ดํด์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํƒ์ง€ ๊ฐ€๋Šฅ.

A* (A - Star)

ํŠน์ • ๋ชฉ์ ์ง€๊นŒ์ง€ ์ตœ๋‹จ ๊ฒฝ๋กœ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜. ํœด๋ฆฌ์Šคํ‹ฑ ํ•จ์ˆ˜ ์‚ฌ์šฉ, ๊ฐ ์ •์ ๊นŒ์ง€์˜ ์˜ˆ์ƒ ๋น„์šฉ ๊ณ„์‚ฐ, ๊ฐ€์žฅ ๋‚ฎ์€ ๋น„์šฉ ๊ฐ€์ง„ ์ •์  ์„ ํƒ ํ›„ ํƒ์ƒ‰.


๋™์  ์•Œ๊ณ ๋ฆฌ์ฆ˜

ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ํ•˜์œ„ ๋ฌธ์ œ๋กœ ๋ถ„ํ• ํ•˜์—ฌ ํ‘ธ๋Š” ์ ‘๊ทผ๋ฐฉ์‹.

  • ์ž‘์€ ํ•˜์œ„ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ๊ณ„์‚ฐ ํ›„ ์ €์žฅ, ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ํฐ ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๋„์ถœ. -> Memoization

  • ์ค‘๋ณต๋˜๋Š” ํ•˜์œ„ ๋ฌธ์ œ๋“ค์„ ํšจ์œจ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ.

  • ์žฌ๊ท€์  ๊ตฌ์กฐ ๊ฐ€์ง.

  • ํ•˜ํ–ฅ์‹ (Top-Down), ์ƒํ–ฅ์‹ (Bottom-Up)

// ๋ฌธ์ œ: ํ”ผ๋ณด๋‚˜์น˜ ์ˆ˜์—ด์˜ n๋ฒˆ์งธ ํ•ญ์„ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.
public int Fibonacci(int n)
{
    int[] dp = new int[n+1];
    dp[0] = 0;
    dp[1] = 1;

    for(int i = 2; i <= n; i++)
    {
        dp[i] = dp[i-1] + dp[i-2];
    }

    return dp[n];
}

์‹œ๊ฐ„ ๋ณต์žก๋„ O(n), ๊ณต๊ฐ„ ๋ณต์žก๋„ O(n)

๊ทธ๋ฆฌ๋”” ์•Œ๊ณ ๋ฆฌ์ฆ˜

๊ฐ ๋‹จ๊ณ„์—์„œ ๊ฐ€์žฅ ์ตœ์ ์ธ ์„ ํƒ์„ ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๊ฐ€์žฅ ์ด์ต์ด ํฐ ์„ ํƒ์„ ํ•˜์—ฌ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ตœ์ ํ•ด์— ๋„๋‹ฌํ•˜๋Š” ์ „๋žต.

  • ์ง€์—ญ์ ์ธ ์ตœ์ ํ•ด๋ฅผ ์ฐพ๋Š”๋ฐ ์ดˆ์ ์„ ๋งž์ถ”๊ธฐ ๋•Œ๋ฌธ์—, ํ•ญ์ƒ ์ „์—ญ์ ์ธ ์ตœ์ ํ•ด ๋ณด์žฅ X

  • ๊ฐ„๋‹จํ•˜๊ณ , ์ง๊ด€์  ์„ค๊ณ„ ๊ฐ€๋Šฅ. ์‹คํ–‰์‹œ๊ฐ„ ๋งค์šฐ ๋น ๋ฆ„.

  • ์ตœ์ ํ•ด๋ฅผ ์ฐพ๋Š” ๋ฌธ์ œ์— ์‚ฌ์šฉ๋˜์ง€๋งŒ, ์ผ๋ถ€ ๋ฌธ์ œ์—์„œ๋Š” ์ตœ์ ํ•ด๋ฅผ ๋ณด์žฅํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Œ.

// ๋ฌธ์ œ: ์ฃผ์–ด์ง„ ๋™์ „๋“ค๋กœ ํŠน์ • ๊ธˆ์•ก์„ ๋งŒ๋“œ๋Š”๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œ ๋™์ „ ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.
public int MinCoins(int[] coins, int amount)
{
    Array.Sort(coins);
    int count = 0;

    for(int i = coins.Length - 1; i >= 0; i--)
    {
        while(amount >= coins[i])
        {
            amount -= coins[i];
            count++;
        }
    }

    if(amount > 0) return -1; 

    return count;
}

์‹œ๊ฐ„ ๋ณต์žก๋„ : O(n) (๋™์ „์— ๋น„๋ก€), ๊ณต๊ฐ„ ๋ณต์žก๋„ : O(1)

๋ถ„ํ•  ์ •๋ณต (Divide and Conquer)

ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ๋ถ€๋ถ„ ๋ฌธ์ œ๋กœ ๋ถ„ํ• , ๋ฌธ์ œ์˜ ํฌ๊ธฐ์— ๋”ฐ๋ฅธ ์„ฑ๋Šฅ ํ–ฅ์ƒ ๊ฐ€๋Šฅ

  • ์žฌ๊ท€์  ๊ตฌ์กฐ, ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์˜ ์„ค๊ณ„๊ฐ€ ๋‹จ์ˆœ, ์ง๊ด€์ 

  • ๋ถ„ํ• ๋œ ๋ถ€๋ถ„ ๋ฌธ์ œ๋“ค์€ ๋…๋ฆฝ์ ์œผ๋กœ ํ•ด๊ฒฐ, ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ์— ์œ ๋ฆฌ

  • ๋ถ€๋ถ„ ๋ฌธ์ œ๋“ค ๊ฐ„ ์ค‘๋ณต ๊ณ„์‚ฐ ๋ฐœ์ƒ ๊ฐ€๋Šฅ. -> Memoization๊ธฐ๋ฒ• ํ™œ์šฉ -> ์„ฑ๋Šฅ ํ–ฅ์ƒ

// ๋ฌธ์ œ: ์ฃผ์–ด์ง„ ๋ฐฐ์—ด์„ ์ •๋ ฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. (ํ€ต ์ •๋ ฌ ์‚ฌ์šฉ)
public void QuickSort(int[] arr, int low, int high)
{
    if(low < high)
    {
        int pi = Partition(arr, low, high);

        QuickSort(arr, low, pi - 1);  // Before pi
        QuickSort(arr, pi + 1, high); // After pi
    }
}

int Partition(int[] arr, int low, int high)
{
    int pivot = arr[high];
    int i = (low - 1);

    for(int j = low; j <= high - 1; j++)
    {
        if(arr[j] < pivot)
        {
            i++;
            Swap(arr, i, j);
        }
    }
    Swap(arr, i + 1, high);
    return (i + 1);
}

void Swap(int[] arr, int a, int b)
{
    int temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;
}

์‹œ๊ฐ„ ๋ณต์žก๋„ : O(n log n) / ์ตœ์•… = O(n^2), ๊ณต๊ฐ„ ๋ณต์žก๋„ : O(log n) (์žฌ๊ท€ ํ˜ธ์ถœ ์Šคํƒ ํฌ๊ธฐ)

๋™์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ vs ๋ถ„ํ•  ์ •๋ณต

  • ๋‘˜ ๋‹ค ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ๋ฌธ์ œ๋กœ ์ชผ๊ฐœ์–ด ์‚ฌ์šฉ.

  • ๋™์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ Memoization์„ ์ด์šฉํ•ด ์ž‘์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด ํ•ด๋‹น ๋ฌธ์ œ์˜ ๊ฐ’์„ ์ €์žฅํ•ด๋†“๋Š”๋‹ค. ์ดํ›„ ํฐ ๋ฌธ์ œ๊ฐ€ ์ž‘์€ ๋ฌธ์ œ์˜ ์ €์žฅ๋œ ๊ฐ’์„ ํ™œ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

  • ๋ถ„ํ•  ์ •๋ณต์€ ํฐ ๋ฌธ์ œ๋ฅผ ์ž‘์€ ๋ฌธ์ œ๋กœ ๋” ์ด์ƒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์„ ๋งŒํผ ์ชผ๊ฐœ์–ด ๋ฌธ์ œ์˜ ํ•ด๋ฅผ ๋ชจ๋‘ ๊ตฌํ•œ ๋’ค ๋ณ‘ํ•ฉํ•˜์—ฌ ํฐ ๋ฌธ์ œ์˜ ๋‹ต์„ ์ฐพ๋Š”๋‹ค.


๐Ÿง ์ˆ˜๊ฐ•ํ›„๊ธฐ

์˜ค๋Š˜์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๊ด€ํ•ด ์—ฌ๋Ÿฌ๊ฐ€์ง€๋ฅผ ๋ฐฐ์› ๋‹ค.

์ •์ฒ˜๊ธฐ๋ฅผ ์ค€๋น„ํ•˜๋ฉด์„œ ์ฃผ์›Œ๋“ค์€ ์šฉ์–ด๋„ ์žˆ์–ด์„œ ์šฉ์–ด ์ž์ฒด๊ฐ€ ์–ด๋ ต์ง€๋Š” ์•Š์•˜๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‚ด ๋จธ๋ฆฟ์†์˜ ํ‘œํ˜„์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋Š”๊ฒŒ ์–ด๋ ค์› ๊ณ ,

์•Œ๊ณ ๋ฆฌ์ฆ˜ ์˜๋„๋ฅผ ํŒŒ์•…ํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ์š”๋๋‹ค.

๊นจ๋‹ฌ์€ ์ ์€,

๋‚ด๊ฐ€ ๋ชจ๋ฅธ๋‹ค๋Š” ๊ฒƒ์„ ๋ถ€์ •ํ•˜์ง€๋ง๊ณ  ์ธ์ •ํ•˜๊ณ , ๋น ๋ฅด๊ฒŒ ํ•™์Šตํ•˜์ž.

๋‚˜๋Š” ์•„์ง ์ดˆ๋ณด์ž๋‹ค. ๊ณ ์ˆ˜๊ฐ€ ๋˜๊ธฐ์œ„ํ•ด ๋‹ค์–‘ํ•œ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ๋‚ด ๊ฒƒ์œผ๋กœ ๋งŒ๋“ค์ž.

๋˜ํ•œ ์—ผ์ธ์ฒ  ํŠœํ„ฐ๋‹˜์ด ๋ง์”€ํ•˜์‹  ๊ฒƒ ์ฒ˜๋Ÿผ

์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋„์‹ํ™”ํ•˜์ž!

๋‚ด๊ฐ€ ์ƒ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ์ด ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ

๋จธ๋ฆฟ์†์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์ตœ๊ณ ์ง€๋งŒ ์•„์ง ๋ ˆ๋ฒจ์ด ๋‚ฎ์œผ๋‹ˆ

๋„์‹ํ™”๋ฅผ ํ†ตํ•ด ํ๋ฆ„์„ ์ดํ•ดํ•˜๊ณ , ์ˆ˜์ •ํ•˜์ž.

๋‚˜๋Š” ์ฒœ์žฌ๊ฐ€ ์•„๋‹˜!


๐Ÿง ๋‚ด์ผ ํ•  ์ผ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌ์ƒํ•˜๊ธฐ.

0๊ฐœ์˜ ๋Œ“๊ธ€