알고리즘 문제(SOL)

[Python,자료구조] Data structure

알고리즘을 풀기위해서, 최소한의 지식만 간단하게 담았습니다. 원래, 하나하나가 게시글 1개 분량으로 쓸 수 있습니다.

깊게 공부할 때, 구체화 시키겠습니다. -수정일. 2022.01.15


배열 (Array)

arr=[]
# 파이썬에서는 리스트로 배열을 구현함.
  • 메모리 상에 연속된 공간으로 할당된다.
  • 삽입(Insert), 삭제(Delete) : O(N)
  • 탐색(Searching): O(1)

삽입,삭제가 O(N)인 이유

더보기
그림판 등장
  • arr[3]이 삭제됬을 때, arr[4]는 앞 자리로 옴. (indx =4 ->3)
  • 그럼, arr[0]이 삭제됬을 때는 , 뒤에 있는 친구들이 다 앞자리로 옮겨야 하므로, 삽입,삭제가 N임. 

탐색이 빠른 이유

  • Random access가 가능하다.
  • 간단하게 배열은 메모리 공간에 연속적이기 때문에, 수식 1개로 해당 데이터로 접근이 가능함.
  • arr[index] = arr의 시작주소+ index*자료형태(string,int등등)

배열이 유리한 상황

  1. 연속적인 자료를 Control 할때.
  2. 탐색을 해야할 때, 잦은 삽입/삭제(수정)이 일어나지 않을때

연결 리스트 (Linked List)

그림판 등장

  • 메모리 상에 Random으로 노드(Node)들이 위치하고, 이들이 주소로 서로를 가리키는 구조
  • 배열과 반대되는 특성을 가짐
  • 삽입(Insert), 삭제(Delete) : O(1)
  • 탐색(Searching): O(N)
  • Python에서는 STL로 구현되어 있지 않고, 자주 쓰이지 않기 때문에 그림판으로 대체!

삽입,삭제가 O(1)인 이유

  • 삽입/삭제가 일어날 때, Node에서 가리키는 주소만 수정해주면 되기 때문에, 삽입, 삭제가 O(1)이다.

탐색이 느린 이유

  • 처음 시작 주소부터, 다음 노드의 주소까지 계속 따라 가야하므로, 어떤 특정 자료를 찾으려면 N번을 다 순회해야한다.

Stack

stk =[]

stk.append("1")
stk.pop()
  • 배열으로 마지막 Index(끝)에서만 삽입,삭제가 일어나는 자료구조 형태이다.
  • 가장 마지막에 들어온 자료(가장 최근의 자료)가 가장 먼저 나간다. LIFO(Last In Fisrt Out),후입선출 등으로 불림
  • 자료를 겹겹이 쌓는 느낌이라, stack이라고 부름. 
  • 파이썬에서는 List로 구현한다.
  • 삽입(Insert),삭제(delete) : O(1)

Queue

from collections import deque

dq= deque([1,2,3])
dq.append(4)

dq.popleft()
  • 맨 앞에서는 자료가 삭제되고, 맨 뒤에서는 자료가 삽입되는 형태임.
  • 줄서는것 처럼, 가장 처음들어온 자료가 가장 먼저 나가게 되는 구조, FIFO(Fisrt In First Out)
  • python에서는 collections에 deque로 구현
  • queue라는게 있지만, Thread-safe때문에, 속도가 느리고 , deque는 양방향에서 모두 삽입/삭제가 일어나서 활용도가 더 좋다.
  • 삽입(insert),삭제(delete): O(1)

deque(double ended queue)

그림판 등장

  • 일반적인 Queue와 다르게, 배열의 처음과 끝에서 모두 Push,pop이 일어나는 형태.
  • Python에서, dq의 앞쪽에서 pop : popleft(), push: appendleft()
  • Python에서 rotate를 이용하면, 데크를 회전시킬 수 있음.
dq = deque([1,2,3,4,5])

dq.rotate(1)
# deque => [5,1,2,3,4]

dq.rotate(-1)
# dqeue => [1,2,3,4,5]

#양수면 오른쪽으로 n만큼 회전, 음수면 왼쪽으로 n 만큼 회전

Priority Queue(우선 순위 큐)

  • Heap이라는 구조로 되어있음. (완전 이진트리)
  • Root에 최댓값을 저장한 Max-heap(C++), 최솟값을  저장한 Min-heap(Python) 2종류가 있음
  • Python에서는 Min-heap이 기본이다.
  • 삽입(Insert)/삭제(Delete):O(logN)
    import heapq as hq
    
    min_heap=[]
    
    hq.headpush(min_heap,456)
    #heapq.headpush(array(list),element)​

Min_heap이 아니라, Max_heap을 이용하고 싶어요!

  • 음수는 커질수록 절대값이 작다. (-1>-2)
  • 양수는 커질수록 절대값이 크다. (2>3)
  • Tuple은 Sorting 할때, 첫번째 index를 이용해서 우선순위를 매긴다.
import heapq
arr=[-1,5,2,3,9,1]
max_heap=[]

for num in arr:
	heapq.heappush(max_heap,(-num,num))
    
while max_heap:
	print(heapq.heappop(max_heap)[1])
# 출력 : 9,5,3,2,1,-1
# 음수는 값이 클수록, 작은 수 니까
#-9 -> -5 -> -3 -> -1 -> 1 순으로 될거고 , 해당 튜플의 값을 보면 Maxheap으로 활용할 수 있음.

map

  • Key - value 구조로 되어있다.
  • key : 중복이 불가능, immutable한 객체
  • Key를 알면, value를 알 수 있으나, value를 안다고 key를 아는건 아니다.
  • Python에서는 dictionary를 이용한다.
  • Python에서는 Hashmap형태로 구현 되어있다.
  • 삽입/삭제 : O(1)
dict={'key':1}

# 값 추가 하는 방법 
# dict[key] = value로 딕셔너리에 추가 가능합니다.
#key에는 List,set이 들어오지 못합니다. (immutable한 객체가 와야함)
dict[111]=10
dict[(1,1)]="this is Tuple key!"
dict[12]=(3,"3")

#키 검사
if 3 in dict:
	print("키가 3인 값이 있습니다")
#값 검사
if "3" in dict.values():
	print('값이 "3"인 map이 있습니다')
#키 값들의 모임
# dict.keys()
for key in dict.keys():
	print(f"key:{key}")
#값들의 모임
#dict.values()
for value in dict.values():
	print(f"values:{value}")
#키-값 pair을 받아오기
# dict.items()
for k,v in dict.items():
	print(f"key:{f}")
    print(f"value:{v}")
#키 값으로, 값 받기
#dict.get('key')
dict.get(111)
dict[111] 
# dict[]방법은, 해당 key가 없으면 error을 반환하기 때문에,비어있을때, NOne을 반환하는 get을 이용하는 것도 좋은방법.
#키 값으로, 해당 딕셔너리 삭제하기
#del['key']
del[(1,1)]

set

  • 중복을 허락하지 않는 자료형. 중학교때 배운 집합을 생각하면 편함.
  • Python에서는 정렬되어 있지 않은 상태(unordered)로 있고, 해쉬로 되어있음.
  • 삽입/삭제: O(1)
s1 = set([1,2,4,5,1])
s1