A Developing Developer
[스파르타코딩클럽] 알고보면 알기쉬운 알고리즘 - 2주차 본문
- 배열(Array) : 크기가 정해진 데이터의 공간
- 한 번 정해지면 바꿀 수 없음
- 각 원소에 즉지 접근 가능
- 원소를 중간에 삽입/삭제 하려면 모든 원소를 다 옮겨야 함 (최악의 경우 O(N)의 시간 복잡도가짐)
- 원소를 새로 추가하려면, 새로운 공간을 할당해야 하므로 매우 비효율적인 자료구조임.
- 클래스 : 분류, 집합 같은 속성과 기능을 가진 객체를 총칭하는 개념이다.
- 객체 : 세상에 존재하는 유일무이한 사물
클래스를 사용하면 같은 속성, 기능을 가진 객체들을 묶어서 정의 가능!
class Person:
def __init__(self, param_name):
print("i am created! ", self)
self.name = param_name
def talk(self):
print('안녕하세요, 제 이름은', self.name, '입니다.')
person_1 = Person('유재석') # 생성자
print(person_1.name)
person_1.talk()
print(person_1) # <__main__.Person object at 0x1090c76d0>
person_2 = Person('박명수')
print(person_2.name)
person_2.talk()
print(person_2) # <__main__.Person object at 0x1034354f0>
# 연관성 있는 데이터들을 클래스 내에서 관리하면서 다양한 객체를 쉽게 생성하기 위해서는 클래스라는 개념을 잘 이용해야한다.
- 링크드리스트(linked list) : 크기가 정해지지 않은 데이터의 공간
- 연결 고리로 이어주기만 하면, 자유자재로 늘어날 수 있음
- 특정 원소에 접근하려면 연결 고리를 따라 탐색해야 함 (최대 O(N)의 시간 복잡도 가짐)
- 원소를 중간에 삽입/삭제 하기위해서는 앞 뒤의 포인터만 변경하면 됨. (O(1)의 시간 복잡도)
각 인덱스 값의 노드는 1) 칸에 있는 데이터(머리) 와 2) 다음 칸이 무엇인지(꼬리) 두가지 정보가 필요하다.
그래서 Node 클래스에서 1) data 와 2) next 를 인자로 받아서 저장한다.
- LinkedList 클래스의 print_all() 함수 : 모든 원소 출력
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self, data):
self.head = Node(data) # head 에 시작하는 Node 를 연결
def append(self, data):
if self.head is None: # head 의 값이 Node 일때
self.head = Node(data) # self.head 에 새로운 데이터 추가
return # 함수 종료
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = Node(data)
def print_all(self):
cur = self.head
while cur is not None:
print(cur.data)
cur = cur.next
linked_list = LinkedList(3)
linked_list.append(4)
linked_list.append(5)
linked_list.print_all()
- 링크드 리스트 원소 찾기 get_node()
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self, value):
self.head = Node(value)
def append(self, value):
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = Node(value)
def print_all(self):
cur = self.head
while cur is not None:
print(cur.data)
cur = cur.next
def get_node(self, index):
node = self.head
cnt = 0
while cnt < index:
node = node.next
cnt += 1
return node
linked_list = LinkedList(5)
linked_list.append(12)
print(linked_list.get_node(0).data) # -> 5를 들고 있는 노드를 반환해야 합니다!
- 링크드 리스트 원소 추가 add_node()
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self, value):
self.head = Node(value)
def append(self, value):
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = Node(value)
def print_all(self):
cur = self.head
while cur is not None:
print(cur.data)
cur = cur.next
def get_node(self, index):
node = self.head
cnt = 0
while cnt < index:
node = node.next
cnt += 1
return node
# index next_node
# ['자갈] ['밀가루'] -> ['우편']
# new_node
# -> ['흑연'] ->
# index.next = new_node
# new_node.next = next_node
def add_node(self, index, value):
if index == 0:
new_node = Node(value) # [6] -> [5]
new_node.next = self.head # head -> [6]
return
new_node = Node(value) # [6]
node = self.get_node(index-1) # [5]
next_node = node.next # [12]
node.next = new_node # [5] -> [6]
new_node.next = next_node # [6] -> [12]
linked_list = LinkedList(5)
linked_list.append(12)
linked_list.append(8)
# [5] -> [6] -> [12] -> [8]
linked_list.add_node(1, 6)
linked_list.print_all()
- 링크드 리스트 원소 삭제 delete_node()
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self, value):
self.head = Node(value)
def append(self, value):
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = Node(value)
def print_all(self):
cur = self.head
while cur is not None:
print(cur.data)
cur = cur.next
def get_node(self, index):
node = self.head
cnt = 0
while cnt < index:
node = node.next
cnt += 1
return node
# index next_node
# ['자갈] ['밀가루'] -> ['우편']
# new_node
# -> ['흑연'] ->
# index.next = new_node
# new_node.next = next_node
def add_node(self, index, value):
new_node = Node(value) # [6]
if index == 0:
new_node.next = self.head # [6] -> [5]
self.head = new_node # head -> [6] -> [5] -> ...
return
new_node = Node(value) # [6]
node = self.get_node(index - 1) # [5]
next_node = node.next # [12]
node.next = new_node # [5] -> [6]
new_node.next = next_node # [6] -> [12]
# ['자갈] ['밀가루'] -> ['우편']
def delete_node(self, index):
if index == 0:
self.head = self.head.next
return # 아래 코드가 실행되지 않도록
node = self.get_node(index - 1)
node.next = node.next.next
linked_list = LinkedList(5)
linked_list.append(12)
linked_list.add_node(0, 3)
linked_list.delete_node(0)
linked_list.print_all()
- 두 링크드 리스트의 합 계산 _get_linked_list_sum()
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self, value):
self.head = Node(value)
def append(self, value):
cur = self.head
while cur.next is not None:
cur = cur.next
cur.next = Node(value)
def get_linked_list_sum(linked_list_1, linked_list_2):
sum_1 = _get_linked_list_sum(linked_list_1)
sum_2 = _get_linked_list_sum(linked_list_2)
return sum_1 + sum_2
def _get_linked_list_sum(linked_list):
linked_list_sum = 0 # linked_list 합계
head = linked_list.head
while head is not None:
linked_list_sum = linked_list_sum * 10 + head.data
head = head.next
return linked_list_sum
linked_list_1 = LinkedList(6)
linked_list_1.append(7)
linked_list_1.append(8)
linked_list_2 = LinkedList(3)
linked_list_2.append(5)
linked_list_2.append(4)
print(get_linked_list_sum(linked_list_1, linked_list_2))
- 이진 탐색 : 반으로 나눠서 진행한다.
finding_target = 14
finding_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
def is_existing_target_number_binary(target, array):
currnet_min = 0
current_max = len(array) - 1
current_guess = (currnet_min + current_max) // 2
while currnet_min <= current_max:
if array[current_guess] == target:
return True
elif array[current_guess] < target:
currnet_min = current_guess + 1
else:
current_max = current_guess - 1
current_guess = (current_max + currnet_min) // 2
return False
result = is_existing_target_number_binary(finding_target, finding_numbers)
print(result)
- 순차 탐색 : 처음부터 순차적으로 진행한다.
- 재귀함수 : 자기 자신을 호출하는 함수
- 재귀 : 어떠한 것을 정의할 때 자기 자신을 참조하는 것
- 카운트 다운
def count_down(number):
if number < 0: # 탈출 조건
return
print(number) # number를 출력하고
count_down(number - 1) # count_down 함수를 number - 1 인자를 주고 다시 호출한다!
count_down(60)
- 팩토리얼
# Factorial(N) = N * Factorial(N-1_
# ...
# Factorial(1) = 1
# factorial(1)
# 5 * 4 * 3 * 2 * 1
def factorial(n): # 1
if n == 1: # True
return 1
return n * factorial(n - 1)
print(factorial(5))
- 회문 검사 (회문 : ["기러기 토마토 스위스 인도인 별똥별 우영우! 거꾸로 해도 우영우! ... 역삼역?" - 우영우-] )
- 반복문
input = "tamato"
# 01234
# 1. index 0 이랑 n-1 같으면 true
# 2. index 1 이랑 n-2 같으면 true
def is_palindrome(string):
n = len(string)
for i in range(n):
if string[i] != string[n - 1 - i]:
return False
return True
print(is_palindrome(input))
- 재귀함수
input = "소주만병만주소"
def is_palindrome(string):
if len(string) <= 1:
return True
if string[0] != string[-1]:
return False
return is_palindrome(string[1: -1])
print(is_palindrome(input))
# 문제가 축소되는 특징이 보여야함
# 특정 구조가 반복되는 것 같은 양상을 보았으면
# 재귀함수 시도 생각
# 재귀함수를 쓸경우 반드시 탈출 조건 작성
============================================================================================
출처 : [스파르타코딩클럽] 알고보면 알기쉬운 알고리즘 - 2주차
============================================================================================
솔직한 심정
(그만해...)
'내일배움캠프 4기 > 자료구조, 알고리즘 KDT 실무형' 카테고리의 다른 글
[스파르타코딩클럽] 알고보면 알기쉬운 알고리즘 - 3주차 (0) | 2022.11.24 |
---|---|
[스파르타코딩클럽] 알고보면 알기쉬운 알고리즘 - 1주차 (0) | 2022.11.22 |