본문 바로가기
TIL

[TIL] 최빈값 찾기

by 좌우지간에 2024. 11. 25.

파이썬 강의복습.

for,while  등 반복문 복습. continue와 break 의 활용예시 익히기.

def 사용자 정의함수와 return의 의미 익히기.

 

프로그래머스 문제풀이.


문제 설명
최빈값은 주어진 값 중에서 가장 자주 나오는 값을 의미합니다. 정수 배열 array가 매개변수로 주어질 때, 최빈값을 return 하도록 solution 함수를 완성해보세요. 최빈값이 여러 개면 -1을 return 합니다.

 

3일차 입문문제인데 난이도가 너무 어렵다.

주어진 정수배열을 하나씩 조회하면서 dictionary에 추가하고 키값을 등장한 횟수로 정해서 풀려고했는데 실패.
였는데 일단 풀었다.

 

1.리스트 두개를 만들어서 각 원소별 등장할때마다 횟수증가.

def solution(array):
	dict_key = []
	dict_value = []

	for i in array:
		if i not in dict_key:
			dict_key.append(i)
			dict_value.append(1)
		else:
			dict_value[dict_key.index(i)] += 1

	max_value = max(dict_value)
	max_index = dict_value.index(max_value)
	mode = dict_key[max_index]

	if dict_value.count(max_value) > 1:
		return -1
	else:
		return mode

코드 설명

 

1. 초기화

dict_key = []
dict_value = []
  • dict_key: 리스트에서 등장한 고유한 값들을 저장.
  • dict_value: 각 고유 값이 몇 번 등장했는지 저장.

2. 리스트 순회 및 값 카운트

for i in array:
    if i not in dict_key:
        dict_key.append(i)
        dict_value.append(1)
    else:
        dict_value[dict_key.index(i)] += 1
  • array를 순회하면서 dict_key와 dict_value를 업데이트합니다.
    • dict_key에 값이 없으면 새로 추가하고, 등장 횟수는 1로 설정.
    • 이미 있으면 dict_key에서 그 값의 인덱스를 찾아 dict_value에서 해당 인덱스의 값을 1 증가시킵니다.

3. 최빈값 찾기

max_value = max(dict_value)
max_index = dict_value.index(max_value)
mode = dict_key[max_index]
  • dict_value에서 가장 큰 값을 max_value로 설정 (최대 등장 횟수).
  • max_value의 인덱스를 찾아 dict_key에서 해당 값을 mode로 저장 (최빈값).

4. 최빈값이 여러 개인지 확인

if dict_value.count(max_value) > 1:
    return -1
else:
    return mode
  • dict_value.count(max_value)로 max_value가 몇 번 등장하는지 확인.
    • 만약 2번 이상 등장하면, 최빈값이 여러 개라는 의미이므로 -1을 반환.
    • 그렇지 않으면 유일한 최빈값인 mode를 반환.

예제 실행

입력: [1, 2, 2, 3, 3]

  1. dict_key = [1, 2, 3]
  2. dict_value = [1, 2, 2]
  3. max_value = 2, max_index = 1, mode = 2
  4. dict_value.count(2) = 2 → 최빈값이 여러 개이므로 결과는 -1.

입력: [1, 2, 2, 3]

  1. dict_key = [1, 2, 3]
  2. dict_value = [1, 2, 1]
  3. max_value = 2, max_index = 1, mode = 2
  4. dict_value.count(2) = 1 → 결과는 2.

 

 

2. count 활용하기.

def solution(array):
    counts = {}
    for i in set(array):
        counts[i] = array.count(i)
    
    # 최빈값 계산
    max_count = max(counts.values())
    modes = [key for key, value in counts.items() if value == max_count]
    
    if len(modes) > 1:
        return -1  # 최빈값이 여러 개
    else:
        return modes[0]  # 유일한 최빈값

이 코드는 리스트 array에서 최빈값을 찾는 함수입니다. 최빈값이 여러 개라면 -1을 반환하고, 유일한 최빈값이 있을 경우 그 값을 반환합니다. 단계별로 설명하겠습니다.


코드 구조 및 설명

1. 빈도 계산을 위한 딕셔너리 생성

counts = {}
for i in set(array):
    counts[i] = array.count(i)
  • 목적: 리스트 array의 각 고유 값이 몇 번 등장했는지를 딕셔너리 counts에 저장.
  • set(array): 리스트에서 중복을 제거해 고유한 값만 얻음.
    • 예: array = [1, 2, 2, 3] → set(array)는 {1, 2, 3}.
  • array.count(i): 리스트 array에서 값 i가 등장하는 횟수를 반환.
  • 결과:
    • 입력 array = [1, 2, 2, 3]이면, counts = {1: 1, 2: 2, 3: 1}.

2. 최빈값의 빈도 계산

max_count = max(counts.values())
  • 목적: 딕셔너리 counts에서 가장 높은 빈도(최대 등장 횟수)를 계산.
  • counts.values()는 counts의 모든 값을 리스트처럼 반환.
    • 예: counts = {1: 1, 2: 2, 3: 1} → counts.values()는 [1, 2, 1].
  • max() 함수로 최댓값을 찾음.
    • 예: max([1, 2, 1]) = 2.

3. 최빈값(들)을 찾기

modes = [key for key, value in counts.items() if value == max_count]
  • 목적: counts에서 max_count와 같은 값을 가진 키(최빈값)를 리스트로 저장.
  • counts.items()는 (key, value) 쌍을 반환.
    • 예: counts = {1: 1, 2: 2, 3: 1} → counts.items()는 [(1, 1), (2, 2), (3, 1)].
  • 리스트 컴프리헨션으로 value == max_count인 key를 modes에 저장.
    • 예: max_count = 2 → modes = [2].

4. 최빈값의 유일성 확인

if len(modes) > 1:
    return -1
else:
    return modes[0]
  • 목적: 최빈값이 여러 개인지 확인하고, 그에 따라 결과를 반환.
  • len(modes) > 1: 최빈값이 여러 개라면 -1 반환.
    • 예: modes = [2, 3] → 최빈값이 2와 3으로 여러 개 → -1 반환.
  • 그렇지 않으면 modes[0] 반환.
    • 예: modes = [2] → 최빈값 2 → 2 반환.

실행 예제

입력 1: array = [1, 2, 2, 3]

  1. 중복 제거 및 카운트:
    • set(array) = {1, 2, 3}
    • counts = {1: 1, 2: 2, 3: 1}
  2. 최빈값 빈도 계산:
    • max_count = max([1, 2, 1]) = 2
  3. 최빈값 찾기:
    • modes = [key for key, value in counts.items() if value == 2] = [2]
  4. 유일성 확인 및 반환:
    • len(modes) == 1 → return modes[0] = 2.

출력: 2


입력 2: array = [1, 2, 2, 3, 3]

  1. 중복 제거 및 카운트:
    • set(array) = {1, 2, 3}
    • counts = {1: 1, 2: 2, 3: 2}
  2. 최빈값 빈도 계산:
    • max_count = max([1, 2, 2]) = 2
  3. 최빈값 찾기:
    • modes = [key for key, value in counts.items() if value == 2] = [2, 3]
  4. 유일성 확인 및 반환:
    • len(modes) > 1 → return -1.

출력: -1


요약

  1. 리스트에서 고유 값을 찾고 각 값의 빈도를 계산.
  2. 최빈값의 빈도와 그 값을 리스트로 저장.
  3. 최빈값이 유일하면 반환하고, 여러 개면 -1 반환.

이 코드의 특징은 가독성이 높고 Python 내장 함수(set, count, max)를 활용해 간단하게 최빈값을 찾는 점입니다.

 

아래는 GPT형님의 개선코드

 

개선점

이 코드는 효율적이지 않습니다. 특히, 리스트에서 index와 count를 반복적으로 호출하기 때문에 큰 입력에서 비효율적입니다. 딕셔너리를 사용해 더 간단하게 구현할 수 있습니다:

개선된 코드

from collections import Counter

def solution(array):
    counts = Counter(array)
    max_count = max(counts.values())
    modes = [key for key, value in counts.items() if value == max_count]

    if len(modes) > 1:
        return -1
    else:
        return modes[0]

이 버전은 더 효율적이고 가독성이 좋습니다. Counter를 사용해 값을 바로 카운트하고, 최빈값을 찾는 과정이 단순화됩니다.

'TIL' 카테고리의 다른 글

[TlL] 241127 개발환경 세팅(iTerm2)  (3) 2024.11.27
[TIL] 241126  (1) 2024.11.26
[TIL] 241122  (1) 2024.11.22
[TIL] 241121  (2) 2024.11.21
[TIL] 241120  (2) 2024.11.20