알고리즘이란?

알고리즘(Algorithm)은 문제를 해결하기 위한 단계적인 절차입니다.

꼭 프로그래밍이 아니더라도, 다양한 분야에서 사용됩니다.

  • 입력(Input)을 받아
  • 정해진 단계(Steps)를 거쳐
  • 원하는 출력(Output)을 만드는 방법

✅ 좋은 알고리즘의 특징

  • 명확성: 단계마다 애매하지 않음
  • 유한성: 언젠가는 끝남
  • 실행 가능성: 실제로 수행할 수 있음
  • 일관성: 같은 입력이면 같은 결과

알고리즘 전투력 측정기, Big-O 표기법

Big-O 표기법입력 크기(n)에 따라 알고리즘이 얼마나 빠른지, 얼마나 많은 메모리를 쓰는지를 표현합니다.

특히 최악의 상황(worst-case) 기준으로 계산하므로 알고리즘의 효율성을 과장하지 않습니다.

 

Big-O 표기법 예시

표현 명칭
O(1) 상수 시간 입력의 크기에 상관없이 항상 일정한 시간이 걸립니다.
O(n) 선형 시간 입력의 크기에 비례하여 시간이 걸립니다.
O(n²) 이차 시간 입력의 크기의 제곱에 비례하여 시간이 걸립니다.
O(log n) 로그 시간 입력의 크기의 로그에 비례하여 시간이 걸립니다.
O(2ⁿ) 지수 시간 입력의 크기의 지수에 비례하여 시간이 걸립니다.

 

Big-O 계산 팁

상수는 무시: O(3n) → O(n)

가장 높은 차수만 남김: O(n² + n) → O(n²)

다항식은 최고 차수 중심: O(5n³ + n² + 2n) → O(n³)

 

시간 복잡도 (Time Complexity)

시간 복잡도란 알고리즘이 문제를 해결하는데 걸리는 시간을 나타내는 척도입니다.

실제 시간(초)이 아니라, 연산 횟수 기준으로 계산합니다.

 

예시 1

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

 

for 반복문이 0부터 n까지 순회하며 합계를 더합니다. 따라서 n회의 연산이 필요하며, 시간 복잡도는 O(n)입니다.

 

예시 2

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

 

두 개의 이중 중첩된 반복문을 포함하고 있습니다.

각 루프는 0부터 n까지 순회하므로, 전체 연산 횟수는 n² 이며, 시간 복잡도는 O(n²)입니다.

 

예시 3

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

재귀적으로 피보나치 수열을 계산하는 함수입니다. 
이 함수는 각 호출마다 두 번의 재귀 호출을 수행하므로, 시간 복잡도는 O(2^n)입니다. 
이는 매우 비효율적인 방법으로
실제 문제 해결에서는 동적 프로그래밍 등의 기법을 사용해 효율성을 높이는 것이 중요합니다.

 

공간 복잡도 (Space Complexity)

알고리즘이 얼마나 많은 메모리를 사용하는지 나타내는 척도입니다. 입력 크기에 따라 변하는 메모리 사용량만 고려합니다.

 

예시 1

// O(n) 시간복잡도, O(1) 공간복잡도
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;
}

 

for 반복문이 있지만 추가적인 메모리 사용이 없으므로 시간 복잡도 O(n), 공간 복잡도 O(1)

 

예시 2

// O(n²) 시간, O(1) 공간
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;
}

 

for 이중 중첩 반복문이 있지만 추가적인 메모리 사용이 없으므로 시간 복잡도 O(n²), 공간 복잡도 O(1)

문제 설명

정수 n과 문자열 control이 주어집니다. 
control은 "w", "a", "s", "d"의 4개의 문자로 이루어져 있으며, 
control의 앞에서부터 순서대로 문자에 따라 n의 값을 바꿉니다.

"w" : n이 1 커집니다.
"s" : n이 1 작아집니다.
"d" : n이 10 커집니다.
"a" : n이 10 작아집니다.
위 규칙에 따라 n을 바꿨을 때 
가장 마지막에 나오는 n의 값을 return 하는 solution 함수를 완성해 주세요.

제한사항

 

-100,000 ≤ n ≤ 100,000
1 ≤ control의 길이 ≤ 100,000
control은 알파벳 소문자 "w", "a", "s", "d"로 이루어진 문자열입니다.
n control result
0 "wsdawsdassw" -1

 


입출력 예 설명

입출력 예 #1

수 n은 control에 따라 다음과 같은 순서로 변하게 됩니다.
0 → 1 → 0 → 10 → 0 → 1 → 0 → 10 → 0 → -1 → -2 → -1
따라서 -1을 return 합니다.

나의 풀이

 
public class Solution 
{
    public int solution(int n, string control) 
    {   
        foreach (char c in control)
        {
            switch (c)
            {
                case 'w':
                    n += 1;
                    break;
                case 's':
                    n -= 1;
                    break;
                case 'd':
                    n += 10;
                    break;
                default:
                    n -= 10;
                    break;
            }
        }
        return n;
    }
}

 

 

🎯 1. 기본적인 수학 함수


 
함수명 설명   사용 예시 실전 팁
Mathf.Abs(x) 절댓값 반환 Mathf.Abs(-10) → 10 거리 계산, 차이 비교할 때 필수
Mathf.Sign(x) 부호 반환: 양수 1, 음수 -1 Mathf.Sign(-5) → -1 방향 계산할 때 활용
Mathf.Clamp(x, min, max) x를 min~max 범위로 고정 Mathf.Clamp(120, 0, 100) → 100 체력, 점수 등 값 제한에 자주 사용
Mathf.Clamp01(x) 0~1 사이로 고정 Mathf.Clamp01(1.2f) → 1 알파 값, 보간 값 등에서 활용
Mathf.Lerp(a, b, t) 선형 보간 (t는 0~1) Mathf.Lerp(0, 100, 0.5f) → 50 부드러운 UI 이동, 값 변화
Mathf.LerpUnclamped(a, b, t) 제한 없는 보간 Mathf.LerpUnclamped(0, 100, 1.5f) → 150 튕기거나 과장된 움직임 표현 시

🔢 2. 각도/회전 관련

함수명 설명 사용 예시 실전 팁
Mathf.Deg2Rad 각도 → 라디안 상수 (1도 = 약 0.017) 30 * Mathf.Deg2Rad Sin, Cos 등에서 사용
Mathf.Rad2Deg 라디안 → 각도 상수 Mathf.Atan2(...) * Mathf.Rad2Deg 라디안 결과를 각도로 보기 좋게
Mathf.Sin(x) / Mathf.Cos(x) 삼각함수 (라디안 기준) Mathf.Sin(Time.time) 주기적인 움직임, 진동 표현
Mathf.Atan2(y, x) 방향 각도 반환 (라디안) Mathf.Atan2(direction.y, direction.x) 2D 캐릭터가 방향을 보는 로직에 사용
Mathf.LerpAngle(a, b, t) 각도 보간 (360도 고려) Mathf.LerpAngle(350, 10, 0.5f) → 0도 회전 애니메이션에 부드럽게 사용
Mathf.MoveTowardsAngle(c, t, d) 특정 각도로 부드럽게 이동 Mathf.MoveTowardsAngle(350, 10, 2f) 일정 속도로 회전할 때
 

🌀 3. 부드러운 이동/변화

 

함수명 설명 사용 예시  실전 팁
Mathf.MoveTowards(current, target, maxDelta) 일정 속도로 target에 접근(등속 운동) Mathf.MoveTowards(0, 100, 5) → 5, 10, 15... 일정 속도 이동 구현 시
Mathf.SmoothDamp(current, target, ref velocity, time) 감속하면서 자연스럽게 이동 Mathf.SmoothDamp(pos, target, ref vel, 0.3f) 따라가는 움직임, 카메라 추적
Mathf.SmoothStep(a, b, t) 곡선처럼 부드럽게 보간 Mathf.SmoothStep(0, 1, 0.5f) → 0.5 UI 애니메이션에서 부드럽게

 


🧮 4. 거듭제곱 / 제곱근 / 로그

 

함수명 설명 사용 예시 실전 팁
Mathf.Pow(x, y) x의 y제곱 Mathf.Pow(2, 3) → 8 비례 가중치나 감쇠 효과 구현
Mathf.Sqrt(x) 제곱근 Mathf.Sqrt(25) → 5 거리 계산 (x² + y²) 할 때
Mathf.Exp(x) e^x Mathf.Exp(1) → 2.718 지수 증가 효과 구현 가능
Mathf.Log(x) 자연로그 (밑 e) Mathf.Log(2.718) → 1 진화, 성장 곡선에 사용 가능
Mathf.Log10(x) 밑 10 로그 Mathf.Log10(1000) → 3 사운드 데시벨 계산 등에 사용

📏 5. 거리 / 비교 등

함수명 설명  사용 예시   실전 팁
Mathf.Approximately(a, b) 거의 같다고 판단 (오차 허용) Mathf.Approximately(0.1f + 0.2f, 0.3f) 부동소수점 비교시 필수
Mathf.Min(a, b) / Mathf.Max(a, b) 최솟값 / 최댓값 Mathf.Min(3, 7) → 3 여러 수 중 조건 제한 시 유용
 

🎲 6. 기타 특수 함수

함수명 설명 사용 예시 실전 팁
Mathf.Repeat(t, length) 값이 length를 넘으면 0부터 반복 Mathf.Repeat(Time.time, 3f) 루프 애니메이션 등에서 주기 유지
Mathf.PingPong(t, length) 값을 왕복 (0 → length → 0 ...) Mathf.PingPong(Time.time, 2f) 좌우/위아래 반사 애니메이션
Mathf.InverseLerp(a, b, value) a와 b 사이에서 value의 위치를
0~1로 환산
Mathf.InverseLerp(0, 100, 50) → 0.5 상대적 위치 계산 (UI, 바 등)
 

🔢 7. 반올림 및 정수 변환

 

함수명 설명 사용 예시 실전 팁
Mathf.Round(x) 가장 가까운 정수로 반올림 (float 반환) Mathf.Round(2.6f) → 3.0f 점수나 값 정렬 시 유용
Mathf.Floor(x) 내림 (float 반환) Mathf.Floor(2.9f) → 2.0f 항상 낮은 방향으로 자를 때
Mathf.Ceil(x) 올림 (float 반환) Mathf.Ceil(2.1f) → 3.0f 남은 수 계산 등에서 유용
Mathf.RoundToInt(x) 반올림 후 정수 반환
(0.5일때 가장 가까운 짝수 반환)
예) 2.5 → 2, 3.5 → 4
Mathf.RoundToInt(2.6f) → 3 실질적인 정수 결과가 필요할 때
Mathf.FloorToInt(x) 내림 후 정수 반환 Mathf.FloorToInt(2.9f) → 2 배열 인덱스 접근 등에 활용
Mathf.CeilToInt(x) 올림 후 정수 반환 Mathf.CeilToInt(2.1f) → 3 최소 수량 계산 등에서 활용

아래와 같이 Finder.cs에 Catch 메서드가 있고

Target.cs에서 찾으려는 상황이 있다고 가정하자

public class Finder : MonoBehaviour
{
    public void Catch()
    {
        Debug.Log("타겟을 찾았다!");
    }
}

 

using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

public class Target : MonoBehaviour
{
    public Finder finder;
    
    void Start()
    {
        finder.Catch();
    }
}

 

보통은 Finder를 참조하여 Finder.cs 내부 메서드에 접근하는데

이는 Catch 메서드가 Public이기 때문이다.

 

그러면 private은 어떻게 접근할 수 있을까?


private 메서드 찾기

 

기본적으로 private로 선언했다면 [외부에선 호출하지 말라는 의도]이므로 강제로 호출하지 않는 것이 좋다.

외부에서도 꼭 호출이 필요하다면 public, protected, 혹은 internal 같은 적절한 접근제한자로 바꾸는 게 더 좋은 설계 

 

Delegate를 사용하여 찾기

public class Finder : MonoBehaviour
{
    public Action onCatch;
    
    private void Catch()
    {
        Debug.Log("타겟을 찾았다!");
    }

    private void Awake()
    {
        onCatch = Catch;
    }
}
public class Target : MonoBehaviour
{

    void Start()
    {
        Finder finder = GameObject.Find("Player").GetComponent<Finder>(); // 어떻게 찾는지는 무관
        finder.onCatch.Invoke();
    }
}

 

내부에서 델리게이트를 등록하고

외부에서 호출하는 방식으로 찾는다.

(public Finder finder를 선언해서 같은 방식으로 onCatch.Invoke를 실행해도 무관)

 

Reflection을 이용하여 찾기

public class Finder : MonoBehaviour
{   
    private void Catch()
    {
        Debug.Log("타겟을 찾았다!");
    }
}

 

public class Target : MonoBehaviour
{
    public Finder finder;

    void Start()
    {        
        MethodInfo method = typeof(Finder).GetMethod("Catch", BindingFlags.NonPublic | BindingFlags.Instance);
        if(method != null)
            method.Invoke(finder, null);
    }
}

 

typeof(Finder)

Finder 클래스의 타입 정보를 가져옵니다.

즉, Finder라는 클래스가 어떤 메서드, 필드 등을 가지고 있는지 조사할 수 있게 해줍니다.

 

GetMethod("Catch", BindingFlags.NonPublic | BindingFlags.Instance)

[Catch]라는 이름의 메서드를 찾습니다.

BindingFlags는 [어떤 접근 수준과 범위에서 찾을지]를 지정합니다.

Flag 의미
NonPublic private, protected 등 공개되지 않은 메서드도 포함해서 찾음
Instance 인스턴스(객체)의 메서드만 찾음 (즉 static 메서드는 제외)

 

 

즉, private void Catch() 같은 비공개 인스턴스 메서드를 찾아주는 설정입니다.

 

method.Invoke(finder, null)

method.Invoke()는 해당 메서드를 강제로 실행합니다.

첫 번째 인자: 실행할 메서드를 포함하는 객체 (finder)

 두 번째 인자: 메서드에 넘길 인자 배열인데, 여기서는 Catch()가 매개변수가 없으므로 null

 

사용을 추천하지 않음 → 퍼포먼스 저하 위험 + 유지보수 어려움

 

SendMessage를 이용하여 찾기

메서드 이름만 문자열로 넘겨서 해당 GameObject에 있는 컴포넌트를 실행할 수 있게 해주는 방식

gameObject.SendMessage("메서드이름", 전달할_값, SendMessageOptions);

해당 GameObject에 붙어 있는 모든 컴포넌트를 검사해서,

문자열로 지정된 이름과 같은 메서드가 있으면 호출합니다.

private 메서드도 호출 가능

 

 

예제 1: 파라미터 없는 메서드 호출

public class Finder : MonoBehaviour
{   
    private void Catch()
    {
        Debug.Log("타겟을 찾았다!");
    }
}
public class Target : MonoBehaviour
{
    public GameObject player;

    void Start()
    {
        player.SendMessage("Catch");
    }
}

 

예제 2: 파라미터 전달

Finder 메서드가 인자를 받는 경우

private void Catch(string name)
{
    Debug.Log($"{name}이 타겟을 찾았다!");
}
player.SendMessage("Catch", "Target1");

 

예제 3: 메서드가 없어도 에러 없이 통과하려면

player.SendMessage("Catch", SendMessageOptions.DontRequireReceiver);

 

만약 [Catch]라는 메서드가 없어도 무시하고 넘어감.

기본은 RequireReceiver: 메서드가 없으면 에러 발생.

Transform.RotateAround(Vector3 point, Vector3 axis, float angle)

: 특정 축을 기준으로 물체를 회전시킨다

    private void Update()
    {
        Rotate();
    }

    private void Rotate()
    {
        transform.RotateAround(transform.parent.position, Vector3.forward, angle * Time.deltaTime);
    }

 

+ Recent posts