카테고리 없음

Data Structures_week2 review

cheonniii 2024. 3. 12. 09:56

1. Complexity Analysis of Algorithms

- Spatial complexity analysis

- Time complexity analysis

2. Asymptotic Notations in Complexity Analysis

- Big O notation

- Big Ω notation

- Big ⊝ notation

3. Recursive Algortihm

Examples

- Summation: Recursion vs. Iteration

- Fibonacci: Recursion vs. Iteration

- Tower of Hanoi

- Fractal


Complexity Analysis of Algorithms

1. Spatial complexity analysis

- Mempory space required for execution

2. Time complexity analysis

    a) Practical Speed

        - Measuring the actual execution time of algorithms 

    b) Theoretical Speed

        - Measure the number of operations performed by the algorithm as a function of data input size n

➡️ Theoretical speed이 합리적 (Free of implementation, Independent of hardware, Independent of software)

 

1. Time Complexity Analysis: Practical

- Measuring the actual execution time of algorithms

import time # importing time module
start_time = time.time() # record start time
sum = 0
for i in range(2000):
sum = sum + i
end_time = time.time() # record end time
elapsed_time = end_time-start_time # the difference is execution time
print('Execution time:', round(elapsed_time,5), 'seconds')

## Execution time: 0.01051 seconds

- difference of end time & start time = execution time

- time: module that measures current time in the processor

 

2. Time Complexity Analysis: Theoretical

- Measure the number of operations performed by the algorithm as a function of data input size . We call the number of operations as a function of n as f(n)

- e.g. Compare 3 algorithms to compute n^2

1) Algorithm 1

    - n * n

    - number of multiplicaton = 1

    - number of assignment = 1

    - In total: 2

def nn_1(n):
out = n*n	# 1 multiple
return out	# 1 assignment: 결과 output에 저장

 

2) Algortithm 2

    - number of summation = n 

    - number of assignment = n + 1

    - In total: 2n + 1

def nn_2(n):
out = 0		# initialize out=0: 1회
for i in range(n):	# iterate n times
	out += n	# summation happens 1 time인데 for loop로 n번 반복되니까 assignment n*1회
return out

 

3) Algorithm 3

    - number of summation = n^2

    - number of assignment = n^2 + 1

    - In total = 2n^2 + 1

def nn_3(n):
out = 0
for i in range(n):
for j in range(n):
out += 1
return out

알고리즘 1이 가장 좋은 결과 보였다

 

Big O, Ω, ⊝ Notation

- Big O: the upper bound of the function (worst-case complexity of an algorithm)

알고리즘의 시간 복잡도 나타내는 표기

- Big Ω: the lower bound of the function (best-case complexity of an algorithm)

- Big ⊝: the lower and upper bound of the function (average-case complexity of an algorithm)

 

Properities of Big O

- 데이터 입력값 n이 충분히 크다고 가정하고 있기 때문에 상수항 무시

- O(N^2 + 2N + 1) → O(N^2)와 같이 영향력이 지배적인 N^2 이외의 항 무시


Recursion

def sum_recursive(n):
 return n + sum_recursive(n-1)
sum_recursive(3)

stopping criteria 없음

⬇️ Base condition is needed to stop the recursion otherwise will run infinitely.

def sum_recursive(n):
 if n < 1:
 return 0
 else:
 return n + sum_recursive(n-1)
sum_recursive(3)

 

Fibonacci Series

1. Recursion

def fib_recursive(n):
 if n < 0:
 print("Incorrect input")
 elif n == 0:
 return 0
 elif n == 1 or n == 2:
 return 1
 else:
 return fib_recursive(n-1)+fib_recursive(n-2)
fib_recursive(8)

T(n) = T(n-1) + T(n-2) + 1

O(2^n)

2. Iteration

def fib_for(n):
 fib = [0,1] + [0]*(n-1)
 for i in range(2, n+1): # run (n-1) times: O(n)
 fib[i] = fib[i-1] + fib[i-2]
 return fib[n]
fib_for(8)

O(n)

recursion is inefficient for Fibonacci Series

→ it becomes worse when n becomes larger