<문제>

https://school.programmers.co.kr/learn/courses/30/lessons/42747

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

 

<풀이>

def solution(citations):
    sorted_list = sorted(citations, reverse=True)
    arr = []

    for i, c in enumerate(sorted_list):
        temp_arr = [i+1, c]
        h_idx = min(temp_arr)
        arr.append(h_idx)

    return max(arr)

 

- 일단 reverse 정렬 (DESC)

- 특정 인용 횟수 이상으로 인용된 논문 개수(i+1)와 인용 횟수(c)를 비교해서 최소값을 저장

- 최소값을 모두 저장한 arr에서 최대값을 찾음

- 아니면 h-index를 특정 조건에 맞으면 갱신하는 방법도 있음

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

세준세비_백준1524  (0) 2025.02.19
[정렬] 좌표압축_백준18870  (0) 2025.02.18
파일 정리_백준20291  (0) 2025.02.17
회전초밥_백준28107  (0) 2025.02.15
절댓값 힙_백준11286  (0) 2025.02.13

 

<문제>

https://www.acmicpc.net/problem/20291

 

 

<풀이>

import sys
from collections import Counter

input = sys.stdin.readline
N = int(input())
all_extension_list = []

for _ in range(N):
    file = input()
    idx = file.find('.')
    all_extension_list.append(file[idx+1:].strip())

e_cnt= Counter(all_extension_list)

sorted_list = sorted(e_cnt)
for extension in sorted_list:
    print(extension, e_cnt[extension])

 

- Counter 활용

- 아니어도 이런 식으로 객체에 간단히 담아서 사용 가능

file = {}
for key in list:
	file[key] = file.get(key, 0) + 1

 

- 아니면 이런식

file = {}
for key in list:
    if key in file:
        file[key] += 1
    else:
        file[key] = 1

 

- 위 풀이로 돌아가서 sort 하고 순회하면서 print

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

[정렬] 좌표압축_백준18870  (0) 2025.02.18
[정렬] H-Index_프로그래머스  (0) 2025.02.17
회전초밥_백준28107  (0) 2025.02.15
절댓값 힙_백준11286  (0) 2025.02.13
크리스마스 선물_백준14235  (0) 2025.02.12

 

<문제>

https://www.acmicpc.net/problem/28107

 

 

<시간 초과 풀이>

import sys

input = sys.stdin.readline
N, M = map(int, input().split())
pref_list = []

for _ in range(N):
    pref_menu_set = set(map(int, input().split()[1:]))
    pref_list.append(pref_menu_set)

food_list = list(map(int, input().split()))
result = [0] * N

for food in food_list:
    for i, pref_menu_set in enumerate(pref_list):
        if food in pref_menu_set:
            pref_menu_set.remove(food)
            result[i] += 1
            break

print(' '.join(map(str, result)))

 

- 손님이 원하는 초밥 리스트를 set으로 하고 손님 순서대로 배열에 담음

- 나오는 초밥을 순회하면서 손님이_원하는_초밥리스트_배열을 다시 순회 (시간초과의 원인인듯)

- 원하는_초밥리스트에 있으면 set에서 remove 후 카운트

- 그래서 나오는 초밥을 key로 한 객체를 사용해야 하나 고민

 

<gpt 풀이>

import sys

input = sys.stdin.read
data = input().split("\n")

# N: 손님 수, M: 초밥 개수
N, M = map(int, data[0].split())

# 손님별 주문 목록과 먹은 초밥 개수
customer_sushi = [set() for _ in range(N)]
customer_count = [0] * N
sushi_to_customers = {}  # {초밥 번호: 먹고 싶은 손님 리스트}

# 손님의 주문 목록을 저장
for i in range(N):
    line = list(map(int, data[i + 1].split()))
    for sushi in line[1:]:  # 첫 번째 값(k)은 필요 없음
        customer_sushi[i].add(sushi)
        if sushi not in sushi_to_customers:
            sushi_to_customers[sushi] = []
        sushi_to_customers[sushi].append(i)  # 해당 초밥을 원하는 손님 리스트에 추가

# 초밥 리스트
sushi_list = list(map(int, data[N + 1].split()))

# 초밥이 나올 때마다 처리
for sushi in sushi_list:
    if sushi in sushi_to_customers:  # 해당 초밥을 원하는 손님이 있다면
        for i in sushi_to_customers[sushi]:  # 그 손님들 중에서
            if sushi in customer_sushi[i]:  # 여전히 초밥을 먹을 수 있다면
                customer_count[i] += 1  # 초밥 개수 증가
                customer_sushi[i].remove(sushi)  # 초밥 제거
                break  # 한 명만 먹을 수 있으므로 종료

# 결과 출력
print(" ".join(map(str, customer_count)))

 

- chatGPT 풀이도 초밥을 key로 담은 객체를 사용, 손님이 원하는 초밥 리스트도 set

- 초밥이 나오는 대로 순회

- 원하는_초밥_리스트 set에서 확인하고 있으면 remove

- 그러나 초밥이 key인 객체에서 값을 빼지 않고 그냥 둬서 시간을 절약 -> 어차피 set에서만 확인하면 됨

- 통과는 됐지만 깔끔한 풀이는 아닌듯

 

 

<다른 풀이>

import sys
from collections import Counter

a = sys.stdin.read().splitlines()
t = int((a[0].split())[0])
food = a[-1].split( )
f_cnt = Counter(food)
cnt = 0
res = []
        
for i in range(1,t+1):
        data = a[i][1::].split( )
        for j in data:
            if f_cnt[j] > 0:
                f_cnt[j] -= 1
                cnt += 1
        res.append(str(cnt))
        cnt = 0
print(' '.join(res))

 

- 다른 사람 풀이

- Counter를 이용 -> 리스트 안에 요소별로 중복되는 횟수를 카운트해서 객체 저장

- 초밥이 나오는 순서가 중요한게 아니라 손님의 순서가 중요하다는 아이디어

- 초밥은 어차피 손님 순서대로 소진하게 되어 있음

- 손님의 초밥 리스트를 순회하면서 나왔던 초밥들을 하나씩 제거하고 카운트

- 어떤 순서가 중요한지 생각하는 것이 포인트, 자료구조는 그 다음

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

[정렬] H-Index_프로그래머스  (0) 2025.02.17
파일 정리_백준20291  (0) 2025.02.17
절댓값 힙_백준11286  (0) 2025.02.13
크리스마스 선물_백준14235  (0) 2025.02.12
RelativeRanks_LeetCode  (0) 2025.02.11

 

<문제>

https://www.acmicpc.net/problem/11286

 

 

<풀이>

import sys
import heapq

input = sys.stdin.readline
N = int(input())
heap = []
m_dict = {}

for _ in range(N):
    x = int(input())

    if x != 0: # push
        if x > 0: # x가 양수일 경우
            heapq.heappush(heap, x)
        else: # x가 음수일 경우
            heapq.heappush(heap, -x)
            if -x in m_dict:
                m_dict[-x] += 1
            else:
                m_dict[-x] = 1
    else: # pop
        if len(heap) == 0: # 배열이 비어있는 경우
            print(0)
        else: # 비어있지 않은 경우
            min = heapq.heappop(heap)
            if min in m_dict: # 미리 저장해둔 마이너스 딕셔너리에 min값에 해당하는 값이 존재하면
                print(-min)
                m_dict[min] -= 1
                if m_dict[min] == 0: # 하나 뽑아서 마이너스 딕셔너리에 해당 키의 값이 0이 되었을때
                    del m_dict[min]
            else: 
                print(min)

 

- 절댓값이라는 조건 때문에 자료구조를 2개 써야 하는 문제

- 위 풀이는 최소힙 + 딕셔너리

- 최소힙에는 양수 정수만 저장해놓고, 딕셔너리에 마이너스로 저장한 값들의 갯수를 모아둔다

- 음수를 저장해야 하는 경우 딕셔너리에 해당 음수의 절댓값을 키로, 값을 +1 해준다

- x = 0에 의해 반대로 숫자들을 뽑아낼 때는 딕셔너리를 검사해서 해당 숫자로 카운트된 적이 있는지 살핀다

- 카운트된 적이 있다면 음수로 변환해주고 딕셔너리에서 -1 해주는데

- 0보다 작아진 값이 카운트값에 들어갈 수 있으니까 0이 되면 아예 delete 해준다

 

 

<다른 풀이>

import sys
# sys.stdin = open('data.txt', 'r')
input = sys.stdin.readline
from heapq import heappop, heappush


def main():
    
    plus_heap = []
    minus_heap = []
    _, *nums = map(int, sys.stdin.buffer.read().split())
    
    for x in nums:
        if x > 0:
            heappush(plus_heap, x)
        elif x < 0:
            heappush(minus_heap, -x)
        else:
            if plus_heap and minus_heap:
                if plus_heap[0] >= minus_heap[0]:
                    temp = -heappop(minus_heap)
                else:
                    temp = heappop(plus_heap)
            elif plus_heap:
                temp = heappop(plus_heap)
            elif minus_heap:
                temp = -heappop(minus_heap)
            else:
                temp = 0
            sys.stdout.write(str(temp) + '\n')


if __name__ == '__main__':
    main()

 

- 최소힙 2개를 쓴 풀이

- 최소힙이지만 음수, 양수를 각각 다른 곳에 저장해두어서 첫번째 값(가장 작은 값)끼리 비교

- 반환할 값을 temp로 저장해놓고 마지막에 반환하는 것도 괜찮아 보인다

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

파일 정리_백준20291  (0) 2025.02.17
회전초밥_백준28107  (0) 2025.02.15
크리스마스 선물_백준14235  (0) 2025.02.12
RelativeRanks_LeetCode  (0) 2025.02.11
더 맵게_프로그래머스  (1) 2025.02.10

 

<문제>

https://www.acmicpc.net/problem/14235

 

 

<풀이>

import sys
import heapq

input = sys.stdin.readline
N = int(input())
heap = []

for _ in range(N):
    cmd = list(map(int, input().split()))
    
    if cmd[0] != 0:
        for i in range(cmd[0]):
            heapq.heappush(heap, -cmd[i+1])
    else:
        if len(heap) == 0:
            print(-1)
        else:
            present = -heapq.heappop(heap)
            print(present)

 

- 가장 가치가 큰 선물을 뽑아줘야 하므로 최대 힙 문제

- 첫째 자리가 0이면 선물을 나눠주고 0이 아니면 충전

- 충전할 때 힙 push

- 선물 줄 때 힙 pop

- 선물 주머니가 비어있을 때는 -1

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

회전초밥_백준28107  (0) 2025.02.15
절댓값 힙_백준11286  (0) 2025.02.13
RelativeRanks_LeetCode  (0) 2025.02.11
더 맵게_프로그래머스  (1) 2025.02.10
균형잡힌 세상_백준4949  (0) 2025.02.08

 

<문제>

https://leetcode.com/problems/relative-ranks/

 

 

<풀이>

import heapq

class Solution:
    def findRelativeRanks(self, score: List[int]) -> List[str]:
            result = [None] * len(score)
            heap = [-n for n in score]
            heapq.heapify(heap)

            for i in range(1, len(score)+1):
                biggest = -heapq.heappop(heap)
                idx = score.index(biggest)

                if i == 1:
                    result[idx] = 'Gold Medal'
                elif i == 2:
                    result[idx] = 'Silver Medal'
                elif i == 3:
                    result[idx] = 'Bronze Medal'
                else:
                    result[idx] = str(i)
            
            return result

 

- 큰 숫자 순서대로 뽑는 것을 생각해서 heap 사용

- 리스트 변환 O(N), heapify O(N)

- heappop(heap) O(log N), index 찾는 부분 O(N) -> 반복문까지 O(N * (N + log N)) = O(N2)

- 전체 시간복잡도는 O(N2)

 

이번엔 해시테이블로 접근

class Solution:
    def findRelativeRanks(self, score: List[int]) -> List[str]:
        sorted_score = sorted(score, reverse=True)
        rank_map = {val:i for i, val in enumerate(sorted_score)}
        ans = []

        for val in score:
            rank = self.convert_rank(rank_map[val])
            ans.append(rank)
        return ans
    
    def convert_rank(self, idx):
        if idx == 0:
            return "Gold Medal"
        elif idx == 1:
            return "Silver Medal"
        elif idx == 2:
            return "Bronze Medal"
        else:
            return str(idx + 1)

 

- sorted 내장함수 시간복잡도는 O(N log N)

- 해시테이블 만드는데 O(N)

- 전체 시간복잡도는 O(N log N)

- 훨씬 간단하면서 빠른 코드가 되었다

- 최소/최대값이라고 무작정 힙을 쓰지 말고 더 효율적인 방법이 있는지 생각해보자

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

절댓값 힙_백준11286  (0) 2025.02.13
크리스마스 선물_백준14235  (0) 2025.02.12
더 맵게_프로그래머스  (1) 2025.02.10
균형잡힌 세상_백준4949  (0) 2025.02.08
식당메뉴_백준26043  (0) 2025.02.06

 

<문제>

https://school.programmers.co.kr/learn/courses/30/lessons/42626?language=python3

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

 

<풀이>

import heapq

def solution(scoville, K):
    answer = 0
    heapq.heapify(scoville)

    while K > scoville[0]:
        least_hot = heapq.heappop(scoville)
        if len(scoville) == 0:
            return -1
        
        second_least_hot = heapq.heappop(scoville)
        new_hot = least_hot + (second_least_hot * 2)
        heapq.heappush(scoville, new_hot)
        answer += 1

    return answer

 

- 배열에서 최소값을 계속 뽑아야 하는 문제 -> 최소힙

- 파이썬은 heapq로 간단히 힙을 사용 가능

- scoville 배열을 heap화 (heapify) 해주고

- 가장 최소값은 배열의 첫번째 값이니까 [0] 인덱스 값을 K와 비교

- 중요한 것은 하나 꺼내고(least_hot) 그 다음 배열에 요소가 남아있는지 확인해야 함 -> 없으면 K이상을 만들 수 없으므로 -1 리턴

- 다시 하나 꺼냄 (second_least_hot)

- 섞고 배열에 push

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

크리스마스 선물_백준14235  (0) 2025.02.12
RelativeRanks_LeetCode  (0) 2025.02.11
균형잡힌 세상_백준4949  (0) 2025.02.08
식당메뉴_백준26043  (0) 2025.02.06
큐_백준10845  (0) 2025.02.05

 

<문제>

https://www.acmicpc.net/problem/4949

 

 

<풀이>

import sys
input = sys.stdin.read().splitlines()
pair = {
    ')' : '(',
    ']' : '['
}
res = []

for str in input:
    if str == '.':
        break

    stack = []

    for s in str:
        if s == '(' or s == '[':
            stack.append(s)
        elif s == ')' or s == ']':
            if len(stack) == 0:
                res.append('no')
                break

            prev_el = stack.pop()
            if prev_el != pair[s]:
                res.append('no')
                break
        elif s == '.':
            res.append('yes') if len(stack) == 0 else res.append('no')
            

print('\n'.join(res))

 

- 비슷한 문제를 많이 풀어봐서 짝 맞추는 건 stack과 pair 해시테이블을 써야겠다고 생각

- 문자열의 문자를 반복하는데 짝의 앞의 것이 오는 경우, 짝의 뒤의 것이 오는 경우, 끝나는 경우 (.)를 나눠서 진행

- 끝났을 때 stack이 비어있으면 yes 아니면 no

'TIL > [파이썬] 1일 1코테' 카테고리의 다른 글

RelativeRanks_LeetCode  (0) 2025.02.11
더 맵게_프로그래머스  (1) 2025.02.10
식당메뉴_백준26043  (0) 2025.02.06
큐_백준10845  (0) 2025.02.05
막대기_백준17608  (0) 2025.02.04

+ Recent posts