algorithm

1405. Longest Happy String

식피두 2020. 9. 14. 16:02

https://leetcode.com/problems/shopping-offers/

 

Shopping Offers - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

a, b, c의 갯수가 주어지고

aaa, bbb, ccc와 같이 연속된 3개의 문자가 나오지 않는 선에서 가장 긴 스트링을 리턴하는 문제

 

한 번 재귀로 접근해보았는데... 계속 예외케이스가 발생하고 결국 중단.

재귀로 푼 다음 메모이제이션으로 최적화가 가능할 것 같았는데...

 

ccaccbcc 예시에서 막힘. 코드가 계속 복잡해지고 시간은 시간대로 잡아먹고, 아이디어는 잘 떠오르지 않아서 솔루션을 참고함.

class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        
        memo = dict()
        
        return_longer = lambda a, b: a if len(a) > len(b) else b
        
        def dfs(an, bn, cn, last):
            key = tuple([an, bn, cn, last])
            if key in memo:
                return memo[key]
            
            ret = ""
            
            if (not last or last[-1] != "a") and an >= 2:
                ret = return_longer(ret, dfs(an-2, bn, cn, last+"aa"))
            if (not last or last[-1] != "b") and bn >= 2:
                ret = return_longer(ret, dfs(an, bn-2, cn, last+"bb"))
            if (not last or last[-1] != "c") and cn >= 2:
                ret = return_longer(ret, dfs(an, bn, cn-2, last+"cc"))
            
            if not ret:
                while an > 0:
                    inserted = False
                    if "bb" in last:
                        last = last.replace("bb", "bab", 1)
                        an -= 1
                        insrted = True
                    elif "cc" in last:
                        last = last.replace("cc", "cac", 1)
                        an -= 1
                        inserted = True
                    if not inserted:
                        break
                while bn > 0:
                    inserted = False
                    if "aa" in last:
                        last = last.replace("aa", "aba", 1)
                        bn -= 1
                        insrted = True
                    elif "cc" in last:
                        last = last.replace("cc", "cbc", 1)
                        bn -= 1
                        inserted = True
                    if not inserted:
                        break
                while cn > 0:
                    inserted = False
                    if "aa" in last:
                        last = last.replace("aa", "aca", 1)
                        cn -= 1
                        insrted = True
                    elif "bb" in last:
                        last = last.replace("bb", "bcb", 1)
                        cn -= 1
                        inserted = True
                    if not inserted:
                        break
                ret = last
                
            memo[key] = ret
            return ret
    
        return dfs(a, b, c, "")

 

20ms top solution

힙 큐를 이용해서 풀었다.

길이에 집중해서 긴 길이의 알파벳 부터 처리함.

heap에서 꺼낸 다음 바로 넣지 않고, 그 다음 것을 꺼내고 나서 넣어야한다.

그렇지 않으면, 갯수가 높은 놈이 계쏙 뽑힐 경우 aa aa aa 같은 상황이 일어날 수 있어서

class Solution:
    def longestDiverseString(self, a: int, b: int, c: int) -> str:
        res = ""
        heap = []
        if a:heapq.heappush(heap, (-a, "a"))
        if b:heapq.heappush(heap, (-b, "b"))
        if c:heapq.heappush(heap, (-c, "c"))
        
        total = a+b+c
        prev_c, prev_cnt = "", 0
        while heap:
            cnt, c = heapq.heappop(heap)
            cnt *= -1
            if prev_cnt > 0:
                heapq.heappush(heap, (-prev_cnt, prev_c))
            if cnt >= 2:
                add = 2 if cnt > total-cnt else 1
                res += c*add
                cnt -= add
                total -= add
            else:
                res += c
                cnt -= 1
                total -= 1
            prev_c, prev_cnt = c, cnt
        return res

'algorithm' 카테고리의 다른 글

735. Asteroid Collision  (0) 2020.10.18
316. Remove Duplicate Letters [R]  (0) 2020.10.18
638. Shopping Offers  (0) 2020.09.12
72. Edit Distance  (0) 2020.09.12
1143. Longest Common Subsequence  (0) 2020.09.10