1. 튜플이란?

튜플(Tuple)은 파이썬의 내장 자료형 중 하나로, 여러 개의 값을 하나의 변수에 저장할 수 있는 자료구조이다. 리스트(List)와 매우 비슷하지만, 튜플은 한 번 생성하면 수정이 불가능(immutable)하다는 차이점이 있다.

따라서 변경이 불필요한 데이터를 안전하게 다룰 때, 데이터의 무결성을 유지하고자 할 때 주로 사용된다.


2. 튜플과 리스트의 비교

항목 튜플 (Tuple) 리스트 (List)

선언 방식 (1, 2, 3) 또는 1, 2, 3 [1, 2, 3]
변경 가능 여부 불가능 (immutable) 가능 (mutable)
속도 상대적으로 빠름 상대적으로 느림
사용 목적 고정된 데이터 처리 데이터 추가, 삭제, 변경 필요할 때

3. 튜플 생성 방법

3-1. 괄호 사용

t1 = (1, 2, 3)

3-2. 괄호 생략 (쉼표만으로도 생성 가능)

t2 = 4, 5, 6

3-3. 한 개의 원소만 포함할 경우 쉼표 필요

t3 = (1,)   # 튜플
t4 = (1)    # 정수형, 튜플 아님

4. 튜플 인덱싱 및 슬라이싱

튜플은 순서가 있는 자료형이므로 인덱스를 통해 접근하거나, 슬라이싱이 가능하다.

t = (10, 20, 30, 40)

print(t[0])    # 10
print(t[-1])   # 40
print(t[1:3])  # (20, 30)

5. 튜플의 불변성

튜플은 생성 이후 값을 변경할 수 없다. 다음 코드는 오류를 발생시킨다.

t = (1, 2, 3)
t[0] = 10      # TypeError: 'tuple' object does not support item assignment

6. 튜플의 활용 예시

6-1. 여러 값 반환

def get_coordinates():
    return (10, 20)

x, y = get_coordinates()
print(x)  # 10
print(y)  # 20

6-2. 반복문에서의 언패킹

points = [(1, 2), (3, 4), (5, 6)]

for x, y in points:
    print(f"x: {x}, y: {y}")

7. 튜플은 큐(queue)에서도 사용된다

collections.deque와 같은 큐에 튜플을 저장하면 데이터와 그에 대한 추가 정보(예: 현재 깊이, 상태 등)를 함께 관리할 수 있다. 이는 BFS(너비 우선 탐색)나 트리 탐색 등에서 매우 유용하게 사용된다.

예시: (노드, 깊이) 형태로 큐에 삽입

from collections import deque

q = deque()
q.append((root, 1))  # 루트 노드와 깊이 1을 함께 저장

while q:
    node, depth = q.popleft()
    print(f"현재 노드 값: {node.value}, 깊이: {depth}")

    if node.left:
        q.append((node.left, depth + 1))
    if node.right:
        q.append((node.right, depth + 1))

위와 같은 방식으로 큐에 튜플을 직접 삽입하고, 언패킹하여 사용하면 상태 관리가 간단해지고 코드가 명확해진다.


8. 결론

튜플은 불변이라는 특성 덕분에 코드의 안정성과 속도를 높이는 데 유리하다. 리스트와 유사하지만 용도에 따라 적절히 선택해야 하며, 변경이 필요 없는 데이터를 다룰 때는 튜플을 사용하는 것이 바람직하다. 또한, 큐와 같은 자료구조에서도 튜플을 사용하면 복합 데이터를 효과적으로 다룰 수 있다.

1. 개념

BFS는 그래프나 트리에서 가장 가까운 노드부터 차례로 탐색해 나가는 알고리즘이다.
주로 큐(Queue) 자료구조를 사용하여 구현하며, 최단 거리 탐색이 필요한 문제에 적합하다.


2. 동작 방식

  1. 시작 노드를 큐에 삽입하고 방문 표시
  2. 큐에서 노드를 하나 꺼냄
  3. 꺼낸 노드의 인접한 노드(또는 자식 노드)를 모두 확인
  4. 아직 방문하지 않은 노드를 큐에 삽입
  5. 큐가 빌 때까지 2~4번 반복

3. 트리 예시로 이해하기

트리 구조 예시

       A
     /   \
    B     C
   / \   / \
  D   E F   G

BFS 탐색 순서

  • 시작 노드: A
  • 방문 순서: A → B → C → D → E → F → G

큐와 방문 순서 변화

단계 큐 상태 방문한 노드

1 [A] []
2 [B, C] [A]
3 [C, D, E] [A, B]
4 [D, E, F, G] [A, B, C]
5 [E, F, G] [A, B, C, D]
6 [F, G] [A, B, C, D, E]
7 [G] [A, B, C, D, E, F]
8 [] [A, B, C, D, E, F, G]

4. 파이썬 코드 예시 (트리 기준)

from collections import deque

class Node:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

def bfs(root):
    if root is None:
        return []

    visited = []
    q = deque([root])

    while q:
        cur_node = q.popleft()
        visited.append(cur_node.value)

        if cur_node.left:
            q.append(cur_node.left)
        if cur_node.right:
            q.append(cur_node.right)

    return visited

nodeD = Node("D")
nodeE = Node("E")
nodeF = Node("F")
nodeG = Node("G")
nodeB = Node("B", left=nodeD, right=nodeE)
nodeC = Node("C", left=nodeF, right=nodeG)
nodeA = Node("A", left=nodeB, right=nodeC)

5. 특징 요약

항목 설명

탐색 순서 가까운 노드부터 레벨 순으로 탐색
자료구조 큐 (Queue)
사용 사례 최단 거리 탐색, 레벨 탐색, 최적 경로 문제 등
시간 복잡도 O(V + E) (V: 정점 수, E: 간선 수)
공간 복잡도 O(V) (큐와 방문 배열 등으로 인해 정점 수 만큼 공간 필요)

 

파이썬 in 키워드 사용하는 부분

파이썬을 공부하다 보면 자주 마주치는 키워드 중 하나가 바로 in입니다.
그런데 이 in이 반복문에도 쓰이고, 조건문에도 쓰이다 보니 처음에는 헷갈리기 쉽습니다.

이번 글에서는 in 키워드의 역할과 의미를 반복문조건문에서 구분해서 설명드릴게요. 예제도 함께 보면서 명확히 이해해 봅시다.


in의 두 가지 주요 역할

1. 반복문에서의 in: 순회(iteration)

for x in iterable:

이 구문에서 in은 순회를 의미합니다. iterable 안에 있는 값을 하나씩 꺼내서 x에 담아 반복합니다.

예제 1: 리스트 순회

numbers = [1, 2, 3]
for n in numbers:
    print(n)

📌 출력:

1
2
3

예제 2: 딕셔너리 순회 (기본은 key 기준)

person = {'name': 'Alice', 'age': 30}
for key in person:
    print(key)

📌 출력:

name
age

딕셔너리는 기본적으로 key만 순회합니다.


2. 조건문에서의 in: 존재 여부 검사

if x in container:

이 구문에서 in은 포함되어 있는지를 묻습니다.
즉, x가 container 안에 있으면 True, 없으면 False입니다.

예제 3: 리스트에서 값 존재 확인

fruits = ['apple', 'banana', 'kiwi']
if 'banana' in fruits:
    print("바나나가 있습니다.")

📌 출력:

바나나가 있습니다.

예제 4: 딕셔너리에서 키 존재 확인

scores = {'Alice': 90, 'Bob': 85}
if 'Alice' in scores:
    print("Alice의 점수는 존재합니다.")

📌 출력:

Alice의 점수는 존재합니다.

주의할 점은, 딕셔너리에 대해 in을 사용할 경우 키(key) 기준으로 존재 여부를 확인한다는 점입니다.


예제 응용: 조건과 반복문에 함께 쓰인 코드 분석

아래는 LeetCode 등에서 자주 나오는 형태입니다.

for num in num_dict:
    if num - 1 not in num_dict:
        cnt = 1
        target = num + 1
        while target in num_dict:
            cnt += 1
            target += 1

여기서 in은 다음처럼 구분됩니다:

  • for num in num_dict: → 딕셔너리의 key를 하나씩 반복
  • if num - 1 not in num_dict: → 특정 key가 존재하지 않는지 검사
  • while target in num_dict: → 특정 key가 존재하는지 검사하여 반복

요약

위치 구문 예시 의미 동작

반복문 for x in iterable: 순회 요소를 하나씩 꺼내 반복
조건문 if x in container: 존재 여부 검사 있으면 True
조건문 if x not in container: 존재하지 않는지 검사 없으면 True

결론

in 하나지만 맥락에 따라 의미가 다릅니다.

  • for 안에 쓰이면 → 순회
  • if, while 안에 쓰이면 → 포함 여부 검사

파이썬 in 연산자 딕셔너리에서 어떻게 동작할까?

딕셔너리에서 in 연산자를 사용할 때 내부적으로 어떻게 동작하는지 궁금해서 찾아봤고, 정리한 내용을 공유합니다.


예시 코드

score = {'music': 100, 'math': 80, 'english': 90}

if 'music' in score:
    print("음악 점수 있음!")  # 출력됨

이 코드는 'music'이라는 키가 score라는 딕셔너리에 존재하는지 확인하는 조건문입니다.


in 연산자의 내부 동작

딕셔너리는 내부적으로 해시 테이블(hash table) 구조로 되어 있음.

if 'music' in score:

이 한 줄이 실행되면 실제로는 이렇게 동작함:

  1. 'music' 키에 대해 hash('music') 계산
  2. 딕셔너리 내부 해시 테이블에서 해당 해시값을 사용해 인덱스 위치를 빠르게 찾음
  3. 그 인덱스에 값이 있으면 True, 없으면 False 반환

즉, 우리가 쓰기엔 간단해 보여도 실제로는 hash 함수 → 빠른 위치 탐색 → 존재 여부 확인 과정이 숨어 있음.


핵심 포인트 정리

내용 설명

구조 딕셔너리는 해시 테이블 기반
in 대상 key 기준으로 존재 여부 확인
내부 동작 hash(key) 계산 후, 인덱스로 바로 접근 (충돌 없으면 O(1))
시간 복잡도 평균 O(1), 최악 O(n) (충돌 많을 경우)
value 확인 if 100 in score.values() 처럼 .values() 사용해야 함

예제 더 보기

키가 존재하는 경우

user = {'id': 101, 'name': 'Alice'}

if 'name' in user:
    print("이름 있음")
# 출력: 이름 있음

키가 없는 경우

if 'email' in user:
    print("이메일 있음")
else:
    print("이메일 없음")
# 출력: 이메일 없음

값(value)을 찾으려면?

if 'Alice' in user.values():
    print("이름이 Alice임")

in은 기본적으로 키에서만 작동하기 때문에 값을 확인하려면 .values() 를 붙여야 함


내가 처음 이해한 방식 요약

if 'music' in score:

→ in 쓰면 내부에서 'music'을 hash() 함수로 해시값으로 바꾸고
→ 그걸로 딕셔너리 내부에서 바로 찾아냄
→ 그래서 마치 random access처럼 빠르게 찾음 


결론

  • in 연산자는 딕셔너리에서 키 존재 여부를 아주 빠르게 확인
  • 해시 테이블 덕분에 평균 시간 복잡도는 O(1)
  • value를 찾고 싶을 땐 .values()를 꼭 사용해야 함

 Python enumerate()와 stack[-1][1] 이해하기

코딩 문제를 풀다 보면 자주 보게 되는 문법 중 하나가 enumerate()와 stack[-1][1]입니다.


1. enumerate()는?

enumerate() 함수는 리스트나 튜플처럼 반복 가능한 객체를 순회할 때,
자동으로 인덱스를 붙여주는 유용한 내장 함수입니다.

기본 문법

for index, value in enumerate(반복가능한객체):
    ...

예시

fruits = ['apple', 'banana', 'cherry']

for i, fruit in enumerate(fruits):
    print(i, fruit)

결과

0 apple
1 banana
2 cherry

즉, enumerate()는 각 요소를 (index, value) 형태의 튜플로 만들어서 반복시켜줍니다.


2. stack[-1][1]은 무슨 뜻?

코딩 문제에서 스택(stack)을 이용할 때 이런 문법을 자주 볼 수 있습니다.

예시 코드

stack = [(0, 30), (1, 40)]
  • stack[-1]: 스택(리스트)의 마지막 요소, 여기서는 (1, 40)
  • stack[-1][1]: 마지막 요소인 튜플의 두 번째 값, 즉 40

다시 말해, stack[-1][1]은 스택의 마지막에 있는 튜플에서 "값"만 뽑아내는 코드입니다.


요약 정리

표현 의미

enumerate() 리스트 요소에 자동으로 인덱스를 붙여줌 (튜플 반환)
stack[-1] 스택의 마지막 요소 (튜플 한 쌍)
stack[-1][1] 마지막 튜플의 두 번째 값 (보통은 온도 등 값 부분)

같이 보면 좋은 예제

def calculateTempDay(temperatures):
    answer = [0] * len(temperatures)
    stack = []

    for cur_day, cur_temp in enumerate(temperatures):
        while stack and stack[-1][1] < cur_temp:
            prev_day, _ = stack.pop()
            answer[prev_day] = cur_day - prev_day
        stack.append((cur_day, cur_temp))

    return answer

print(calculateTempDay([30, 40, 50, 60]))  # 출력: [1, 1, 1, 0]

이 예제에서는 enumerate()로 날짜(인덱스)와 온도를 동시에 다루고
stack[-1][1]을 사용해 이전 날의 온도와 비교하고 있어요.

 

관련 문제 링크

문제 링크

🔗 Programmers - 아픈 동물 조회 문제


문제 요약

  • 요구사항
    동물 보호소에 들어온 동물 중 아픈 동물의 아이디와 이름을 조회합니다.
    결과는 아이디 순으로 정렬되어야 합니다.
  • 출력 컬럼
    ANIMAL_ID, NAME

문제 내용

동물 보호소에 들어온 동물 중 아픈 동물만 조회하는 SQL문을 작성해 주세요.
조건에 맞는 동물들을 ANIMAL_ID 순으로 정렬합니다.


풀이 과정 및 코드

풀이 과정

  1. 데이터베이스 테이블: ANIMAL_INS
    • 동물의 아이디, 이름, 상태(INTAKE_CONDITION)가 저장된 테이블.
  2. 조회 조건:
    • INTAKE_CONDITION = 'Sick'인 데이터만 조회.
  3. 정렬 기준:
    • ANIMAL_ID 순으로 오름차순(ORDER BY ANIMAL_ID ASC).
  4. 필요한 컬럼:
    • ANIMAL_ID, NAME

SQL 코드

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS 
WHERE INTAKE_CONDITION = 'Sick';

SQL 개념 정리

  • WHERE: 조건을 지정하여 데이터를 필터링하는 SQL 명령어.
  • ORDER BY: 정렬을 수행하는 SQL 명령어.
    • 기본값은 오름차순(ASC) 정렬입니다.

문제 링크

🔗 Programmers - 동물 보호소 데이터 조회 문제 (ANIMAL_ID순)


문제 요약

  • 요구사항
    동물 보호소에 들어온 모든 동물의 아이디와 이름을 ANIMAL_ID 순으로 조회합니다.
  • 출력 컬럼
    ANIMAL_ID, NAME

문제 내용

동물 보호소에 들어온 모든 동물의 아이디와 이름을 ANIMAL_ID 순으로 조회하는 SQL문을 작성해 주세요.


풀이 과정 및 코드

풀이 과정

  1. 데이터베이스 테이블: ANIMAL_INS
    • 동물의 아이디와 이름이 저장된 테이블.
  2. 정렬 기준:
    • ANIMAL_ID 순으로 오름차순(ORDER BY ANIMAL_ID ASC).
  3. 필요한 컬럼:
    • ANIMAL_ID, NAME

SQL 코드

SELECT ANIMAL_ID, NAME FROM ANIMAL_INS ORDER BY ANIMAL_ID;
SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;​

SQL 개념 정리

  • ORDER BY: 정렬을 수행하는 SQL 명령어.
    • 기본값은 오름차순(ASC) 정렬입니다.
문제 링크

🔗 Programmers - 동물 보호소 가장 먼저 들어온 동물 조회 문제


문제 요약

  • 요구사항
    동물 보호소에 가장 먼저 들어온 동물의 이름을 조회합니다.
  • 출력 컬럼
    NAME

문제 내용

동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하는 SQL문을 작성해 주세요.


풀이 과정 및 코드

풀이 과정

  1. 데이터베이스 테이블: ANIMAL_INS
    • 동물의 이름과 보호 시작일(DATETIME)이 저장된 테이블.
  2. 정렬 기준:
    • 보호 시작일(DATETIME) 기준 오름차순(ORDER BY DATETIME ASC).
  3. 제한 조건:
    • 가장 먼저 들어온 동물 1마리만 조회(LIMIT 1).
  4. 필요한 컬럼:
    • NAME

SQL 코드

 
SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME ASC LIMIT 1;
SELECT NAME
FROM ANIMAL_INS
ORDER BY DATETIME ASC LIMIT 1;​

 


SQL 개념 정리

  • ORDER BY: 정렬을 수행하는 SQL 명령어.
    • ASC: 오름차순 정렬(생략가능)
  • LIMIT: 결과의 출력 개수를 제한하는 SQL 명령어.
    • LIMIT 1: 결과를 1개로 제한.

문제 링크

🔗 Programmers - 동물 보호소 데이터 조회 문제


문제 요약

  • 요구사항
    동물 보호소에 들어온 모든 동물의 이름보호 시작일을 조회합니다.
    결과는 ANIMAL_ID를 기준으로 내림차순(역순)으로 정렬되어야 합니다.
  • 출력 컬럼
    NAME, DATETIME

문제 내용

동물 보호소에 들어온 모든 동물의 이름과 보호 시작일을 조회하는 SQL문을 작성해주세요.
결과는 ANIMAL_ID의 역순으로 정렬되어야 합니다.


풀이 과정 및 코드

풀이 과정

  1. 데이터베이스 테이블: ANIMAL_INS
    • 동물의 이름과 보호 시작일이 저장된 테이블.
  2. 정렬 기준:
    • ANIMAL_ID를 기준으로 내림차순(ORDER BY ANIMAL_ID DESC).
  3. 필요한 컬럼:
    • NAME, DATETIME.

SQL 코드

SELECT NAME, DATETIME
FROM ANIMAL_INS 
ORDER BY ANIMAL_ID DESC;​

 

문제 링크

🔗 Programmers - 동물 보호소 이름 정렬 문제


문제 요약

  • 요구사항
    동물 보호소에 들어온 모든 동물의 아이디, 이름, 보호 시작일을 이름 순으로 정렬하여 조회합니다.
    이름이 같은 동물이 있을 경우, 보호를 나중에 시작한 동물이 먼저 나오도록 설정해야 합니다.
  • 출력 컬럼
    ANIMAL_ID, NAME, DATETIME

문제 내용

동물 보호소에 들어온 모든 동물의 아이디와 이름, 보호 시작일을 이름 순으로 조회하는 SQL문을 작성해 주세요.
단, 이름이 같은 동물 중에서는 보호를 나중에 시작한 동물을 먼저 보여줘야 합니다.


풀이 과정 및 코드

풀이 과정

  1. 데이터베이스 테이블: ANIMAL_INS
    • 동물의 아이디, 이름, 보호 시작일이 저장된 테이블.
  2. 정렬 기준:
    • 이름 순으로 오름차순(ORDER BY NAME ASC).
    • 같은 이름일 경우, 보호 시작일을 기준으로 내림차순(ORDER BY DATETIME DESC).
  3. 필요한 컬럼:
    • ANIMAL_ID, NAME, DATETIME.

SQL 코드

SELECT ANIMAL_ID, NAME, DATETIME 
FROM ANIMAL_INS
ORDER BY NAME, DATETIME DESC;

 

SQL 개념 정리

  • ORDER BY: 정렬을 수행하는 SQL 명령어.
    • ASC: 오름차순 정렬.
    • DESC: 내림차순 정렬.

+ Recent posts