Python/알고리즘 연습

3. 동명이인 찾기 ①

김아다만티움 2024. 7. 11. 15:15

 

* 책: 모두의 알고리즘 with 파이썬 


 n명의 사람 이름 중에서 같은 이름을 찾아 집합으로 만들어 돌려주는 알고리즘을 만들어보세요.

  • n명의 이름이 들어있는 리스트에서 같은 이름이 있는지 확인
  • 같은 이름이 있을 경우 새로 만든 집합에 넣어서 return 

 

1. 선행 개념: 집합 (set)

리스트와 마찬가지로 정보를 여러개 넣어서 보관할 수 있는 파이썬 자료형

  • 단, 같은 자료가 중복되서 들어가지 않으며
  • 자료의 순서도 무관함: {1, 2} = {2, 1}

 

※ 자주 쓰이는 집합 기능 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
########### len(s): 집합 s의 길이(자료 개수) ################
 
= set() # 새 집합 만들기
len(s) # 새 집합이므로 0
len({1,2,3}) # 자료 개수가 세 개 = 3
 
 
########### s.add(x): 집합 s에 x를 추가 #####################
 
= {123}
s.add(4# {1, 2, 3, 4}
 
 
########### s.discard(x): 집합에 x가 들어있을 경우 삭제 ######
# 없으면 아무런 변화 X 
 
s.discard(5# {1,2,3,4}
s.discard(4# {1,2,3}
 
 
########### s.clear(): 집합 내 모든 요소 없애기 ############## 
 
s.clear() # {}
 
 
########### x in s: 집합 s에 x가 있는지 Boolean으로 확인 #####
 
4 in s # False
4 not in s # True
1 in s # True
cs

 

 

2. 동명이인을 찾는 알고리즘

    1) 리스트 첫 번째 요소와 나머지 요소들을 비교

    2) 리스트 두 번째 요소와 첫 번째 요소를 제외한 나머지 요소들을 비교

    3) 리스트 마지막 요소는 아무와도 비교할 필요가 없음

   4) 같은 이름이 있을 경우 집합에 추가 

1
2
3
4
5
6
7
8
9
def find_same_name(names):
    n = len(names)
    result_set = set()
    for i in range(0, n-1):
        for j in range(i+1, n):
            if names[i] == names[j]:
                result_set.add(names[i])
 
    return result_set
cs

 

위 코드에서 중첩 반복문이 핵심 

    1) for i in range(0, n-1): 확인하고 싶은 이름으로, 리스트의 마지막 이름은 제외

    2) for j in range(i+1, n): 비교 대상 이름으로, i보다는 항상 뒤의 이름; (리스트 길이-1)의 인덱스를 가지는 끝 이름까지 포함

 

3. 계산 복잡도? 

    두 이름이 같은지 '비교'하는 횟수를 따짐 

    결론적으로 1/2n² - 1/2n 이므로 O(n²)

      ⇒ 입력크기 n이 커질수록 제곱에 비례하여 연산 시간이 증가함 wow

 

 

<연습 문제> 

n명 중 두 명을 뽑아 짝을 짓는다고 할 때 짝을 지을 수 있는 모든 조합을 출력하는 알고리즘을 만들어보세요. 

    1) 사람 이름이 들어간 리스트 n

    2) 리스트에서 두 명씩 짝짓기

    3) 2)에서 얻은 짝 중 중복은 없애기 

    4) 조합 출력 코드 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
name_lists = ['amy''brad''cindy''diana''emily''frank''gina']
 
def my_bf(names):
    n = len(names)
    pairs = set()
    for i in range(0, n-1):
        for j in range(i+1, n):
            pairs.add(str(names[i]+'-'+names[j]))
    return pairs
 
my_bf(name_lists) # n(n-1)/2 의 조합
"""'amy-brad', 'amy-cindy', 'amy-diana', 'amy-emily', 'amy-frank',"""  
""" 'amy-gina', 'brad-cindy', 'brad-diana', 'brad-emily', 'brad-frank',"""
""" 'brad-gina', 'cindy-diana', 'cindy-emily', 'cindy-frank', 'cindy-gina',"""
""" 'diana-emily', 'diana-frank', 'diana-gina', 'emily-frank', 'emily-gina', 'frank-gina'"""
cs

 

# 오답노트

처음에는 아래 코드와 같이 짰더니 6쌍밖에 나오지 않음

모든 경우의 수 고려가 아닌 바로 뒤의 요소하고만 짝을 지어주었기 때문 ~_~

1
2
3
4
5
6
7
8
9
10
name_lists = ['amy''brad''cindy''diana''emily''frank''gina']
 
def my_bf(names):
    n = len(names)
    pairs = set()
    for i in range(0, n-1):
        pairs.add(str(names[i]+'-'+names[i+1]))
    return pairs
 
my_bf(name_lists) """ 'amy-brad',  'brad-cindy', 'cindy-diana', 'diana-emily', 'emily-frank', 'frank-gina'"""
cs