탐욕법(greedy) - 큰 수 만들기

krystal·2023년 10월 3일
0

코딩테스트 대비

목록 보기
3/11

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

근데 이렇게 하면 문제점이 있다. 마지막 예시에서 걸린다는 점. 어쩐지 너무 단순하게 생각한다 했다.

우선 초기 코드는 다음과 같다. (코드 정리를 제대로 하지않아 필요없는 중복된 변수가 있다던지 .. 좀 엉망이다)

def solution(number, k):
    
    number = list(map(int, number))
    _number = number[:]
    __number = number[:]
    n = len(number) - k
    answer = list()
    
    while True: # 제일 앞 자리에 둘 숫자를 구하기
        max_number = max(_number)
        max_idx = number.index(max_number)
        if max_idx <= n:
            answer.append(max_idx)
            break
        else: # 만약 큰 숫자가 중복으로 나올 수 있으니, idx가 잘 안나올 수 있음을 방지
            number[max_idx] = -1
            del _number[max_idx]
    
    number = __number[:]
    _number = number[max_idx:]
    ct = k - max_idx
    while True: # 제일 작은 숫자 구하기
        if ct == 0:
            break
        min_number = min(_number)
        min_idx = _number.index(min_number)
        answer.append(min_number)
        ct -= 1
        _number[min_idx] = 100
        

    number = number[max_idx:]
    for i in answer[1:]:
        number.remove(i)  
    return ''.join(str(s) for s in number)

일단 실행시간도 걸리는지 확인할 겸 제출을 해보자.
음 당연하듯이 오래걸린다.. 실행시간도 오래 걸린다 ^^ 총체적 난국!
테스트 케이스 1,7,8,10 이 시간 초과로 걸린다.

아 생각해보니 정렬을 안했네. 정렬이 키워드일 것같다.
정렬을 해보고 다시 해보자. ... 라 했지만 잘 안된다.

구글링을 통해 좀더 생각 정리를 해보았다.
스택 이라는 방법이 있었다.
그렇지 ..애초에 리스트를 0번째부터 지나가면서 제거할 숫자를 고르는거니까 스택을 생각하는게 맞겠다 싶었다.

참고한 풀이 링크

하 진짜 다들 천재인가 싶다.. 내가 너무 복잡하게 생각했음
코드가 확 줄여지는 거 보고 자괴감이 들었다

def solution(number, k):
    answer = []
    for num in number: #1,9,2,4
        # 남은 자릿수가 있고, 스택이 비어있지 않으며, 
        # 스택의 마지막에 쌓인 것이 현재 num보다 작을 때
        print(answer, num)
        
        # answer[-1] < num 일 때 pop 하는 이유는?
        # 최적으로 큰 수를 구해야하는데 지금 나온 숫자가 더 크면 개를 써야지
        while k > 0 and answer and answer[-1] < num:
            answer.pop()
            k -= 1
        # 처음엔 스택이 비어있음 => [1]
        answer.append(num)
    print(answer)
    return ''

돌아가는 순서는 다음과 같다

가장 최적의 수를 계속해서 stack에 적립을 해주고 만약 더 큰게 있으면 걔를 넣어주고 그런식의 반복
while문을 통해서 만약 ct 범위 내에 가장 큰 수가 나오면 모두 pop해서 없애주는 형식임. ㄹㅇ 천재인가 ㅠ 진짜 왜 저렇게 생각을 못했지

def solution(number, k):
    answer = []
    for num in number: #1,9,2,4
        # 남은 자릿수가 있고, 스택이 비어있지 않으며, 
        # 스택의 마지막에 쌓인 것이 현재 num보다 작을 때        
        # answer[-1] < num 일 때 pop 하는 이유는?
        # 최적으로 큰 수를 구해야하는데 지금 나온 숫자가 더 크면 개를 써야지
        while k > 0 and answer and answer[-1] < num:
            answer.pop()
            k -= 1
        # 처음엔 스택이 비어있음 => [1]
        answer.append(num)
    return ''.join(num for num in answer)

근데 이렇게 해주니까 마지막 테스트 케이스에서 걸린다.

이번에도 열심히 구글링..
k를 중심으로 프린트 해보니까 오류나는 테스트케이스에서 k가 남아있었다. 그럼 걔를 제외해보고 프린트 해보았다.
답이 나오는 걸 볼 수 있었다. 그럼 다시 return값을 조정해주자.

드디어 완ㄹ료 ^^.... 나 코테 합격할 수 있을까.. 막막하다

def solution(number, k):
    answer = []
    n = k
    for num in number: #1,9,2,4
        # 남은 자릿수가 있고, 스택이 비어있지 않으며, 
        # 스택의 마지막에 쌓인 것이 현재 num보다 작을 때        
        # answer[-1] < num 일 때 pop 하는 이유는?
        # 최적으로 큰 수를 구해야하는데 지금 나온 숫자가 더 크면 개를 써야지
        while k > 0 and answer and answer[-1] < num:
            answer.pop()
            k -= 1
        # 처음엔 스택이 비어있음 => [1]
        answer.append(num)
    return ''.join(answer[:len(answer)-k])
profile
https://source-coding.tistory.com/

0개의 댓글