Sad Puppy 3 'CodingTest/문제 풀이 - Python' 카테고리의 글 목록 (3 Page) :: 개발자 아지트

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

N x N 크기인 정사각 격자 형태의 지형이 있습니다. 각 격자 칸은 1 x 1 크기이며, 숫자가 하나씩 적혀있습니다. 격자 칸에 적힌 숫자는 그 칸의 높이를 나타냅니다.

 

이 지형의 아무 칸에서나 출발해 모든 칸을 방문하는 탐험을 떠나려 합니다. 칸을 이동할 때는 상, , , 우로 한 칸씩 이동할 수 있는데, 현재 칸과 이동하려는 칸의 높이 차가 height 이하여야 합니다. 높이 차가 height 보다 많이 나는 경우에는 사다리를 설치해서 이동할 수 있습니다. 이때, 사다리를 설치하는데 두 격자 칸의 높이차만큼 비용이 듭니다. 따라서, 최대한 적은 비용이 들도록 사다리를 설치해서 모든 칸으로 이동 가능하도록 해야 합니다. 설치할 수 있는 사다리 개수에 제한은 없으며, 설치한 사다리는 철거하지 않습니다.

 

각 격자칸의 높이가 담긴 2차원 배열 land와 이동 가능한 최대 높이차 height가 매개변수로 주어질 때, 모든 칸을 방문하기 위해 필요한 사다리 설치 비용의 최솟값을 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • land는 N x N크기인 2차원 배열입니다.
  • land의 최소 크기는 4 x 4, 최대 크기는 300 x 300입니다.
  • land의 원소는 각 격자 칸의 높이를 나타냅니다.
  • 격자 칸의 높이는 1 이상 10,000 이하인 자연수입니다.
  • height는 1 이상 10,000 이하인 자연수입니다.

 

문제 해결 방법

 

BFS를 활용해서 문제를 풀었다. 그런데 BFS를 할 때, 고려해줘야 하는게 있었다. 

바로 사다리 설치비용이다. 문제에서 요구한대로 최소한의 사다리 설치 비용을 산출해내야 되기 때문에, 좌표에서 상, 하, 좌, 우 이동시 발생할 수 있는 사다리 설치 비용에 대해서 우선순위를 매겨야한다. 이때 heapq 우선순위 큐를 활용하여 문제를 해결했다. 

 

 

코드 구현

 

BFS, heapq 자료구조를 이용해 풀이한 코드

import heapq 

def solution(land, height):
    answer = 0
    # 좌표 움직임을 위한 배열
    dx = [0, 0, -1, 1]
    dy = [1, -1, 0, 0]
    
    #시작 좌표
    startX, startY = 0, 0
    
    # 방문 여부 확인을 위한 배열
    visited = [[False] * len(land) for _ in range(len(land[0]))]
    
    heap = []
    
    
    def bfs(stratX, startY):
        answer = 0
        heapq.heappush(heap, [0, startX, startY]) # 비용, startX, startY
        
        while len(heap) != 0:
            cost, x, y = heapq.heappop(heap)
            #print('cost', cost)
            
            
            if visited[y][x] == False:
                visited[y][x] = True
                
                answer += cost
                for i in range(4):
                    nx = x + dx[i]
                    ny = y + dy[i]
                    
                    # 새로운 좌표가 정사각 격자 형태의 지형을 벗어나는지 체크
                    if ny >= len(land) or nx >= len(land[0]) or ny < 0 or nx < 0:
                        continue
                    
                    if abs(land[y][x]-land[ny][nx]) <= height:
                        newcost = 0
                        
                    else:
                        newcost = abs(land[y][x]-land[ny][nx])
                        
                    heapq.heappush(heap, [newcost, nx, ny])
        return answer
        
        
    answer = bfs(startX, startY)          
    #print(answer)
    
    return answer

 

 

 

BFS구현 및 deque로 구현하려다가 실패한 코드

 

from collections import deque

def solution(land, height):
    answer = 0
    realAnswer = 0
    # 좌표 움직임을 위한 배열
    dx = [0, 0, -1, 1]
    dy = [1, -1, 0, 0]
    
    #시작 좌표
    startX, startY = 0, 0
    
    # 방문 여부 확인을 위한 배열
    visited = [[False] * len(land) for _ in range(len(land[0]))]
    
    check = [[10000] * len(land[0]) for _ in range(len(land))]
    
    print(visited)
    
    queue = deque()
    
    def bfs(stratX, startY):
        
        #시작하는 좌표를 큐에 넣고, 
        
        # 큐에 값이 있으면 큐에서 값을 꺼내어 방문 처리를 한다. 
        # 꺼낸 값에 인접한 값 중에서 방문하지 않은 좌표인지 확인한 후, 
        # 방문하지 않았으면 큐에 넣는다.
        
        queue.append([startX, startY])
        nx = 0
        ny = 0
        
        while len(queue) != 0:
            x, y = queue.popleft()
            visited[y][x] = True
            print('')
            print('x, y', x, y)
            for i in range(4):
                nx = x + dx[i]
                ny = y + dy[i]
                print('i', i, 'nx, ny:', nx, ny)
                # 새로운 좌표가 정사각 격자 형태의 지형을 벗어나는지 체크
                if ny >= len(land) or nx >= len(land[0]) or ny < 0 or nx < 0:
                    print('?1')
                    continue
                
                if visited[ny][nx] == True:
                    print(visited)
                    print('?2')
                    continue
                
                print('nx, ny', nx, ny, 'x', 'y', x, y)
                print(land[y][x], land[ny][nx])
                if abs(land[y][x]-land[ny][nx]) <= height:
                    check[ny][nx] = abs(land[y][x]-land[ny][nx])
                    print('input', nx, ny)
                    queue.append([nx, ny])
#                 else:
#                     if check[ny][nx] > abs(land[y][x]-land[ny][nx]):
#                         check[ny][nx] = abs(land[y][x]-land[ny][nx])
                    
#                     print('input', nx, ny)
#                     queue.append([nx, ny])
    
    
    bfs(startX, startY)
    check[0][0]=0    
    print('check', check)           
        
    
    
    
    
    
    
    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N^2log(N^2))

 

최적화 및 개선 / 어려웠던 점

 

진짜 BFS에서 좌표 문제는 항상 헷갈리는 것 같다. 

이 문제를 풀면서 깨달은 것은 이차원배열에서 x, y 좌표의 값을 구하고 싶으면

 

이차원배열명[y][x]

이렇게 호출해야 한다는 점이다. 

 

그리고 heapq와 deque의 사용처에 대해서 분명히 알게됐다. 

heapq는 deque보다 자료의 우선순위를 매겨야 할 때 사용하는 것이 적절하다. 

반대로 자료의 우선순위를 매겨야할 때 deque를 사용하는 것은 적절치 않다. 

 

 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.

 

예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.

 

0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.

 

제한 사항

numbers의 길이는 1 이상 100,000 이하입니다.

numbers의 원소는 0 이상 1,000 이하입니다.

정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.

입출력 예

numbers return

[6, 10, 2] "6210"

[3, 30, 34, 5, 9]    "9534330"

 

문제 해결 방법

 

주어진 값들의 대소비교를 원활하게 하기 위해서, 3배를 취해준뒤, 내림차순으로 정렬하였다. 

중복제거를 위해 집합을 사용했다. 

 

코드 구현

 

def solution(numbers):
    answer = ''
    
    sortedNum = []
    numbers = list(map(str, numbers))
    numbers.sort(reverse=True)
    
    numbers.sort(key=lambda x : x*3, reverse=True)
    numbers = list(map(int, numbers))
    
#     i = len(numbers)-1

#     while 1:
#         if i == 0:
#             break
#         if int(str(numbers[i-1]) + str(numbers[i])) >= int(str(numbers[i]) + str(numbers[i-1])):
#             i -=1
#             continue
#         else:
#             tmp = numbers[i]
#             numbers[i]=numbers[i-1]
#             numbers[i-1]=tmp
        
#         i = len(numbers)-1

    if max(numbers)==0:
        return '0'
    
    numbers = list(map(str, numbers))
            
    answer = ''.join(numbers)
    return answer

 

# 사실 주석처리 한 부분처럼 구현하려 했으나, 쓸모없어졌다. 

 

시간/공간 복잡도

 

O(n)

 

최적화 및 개선

 

하지않음 

 


어려웠던 점

 

진짜 볼때마다 아주 놀라운 문제다 싶다. 

숫자의 대소비교를 할때, 문자열로 형태를 변환한 뒤,  제한사항에서 주어진 값의 값의 범위를 참고하여 값을 임의로 부풀려 대소비교를 하는 방법을 잊지 말도록 하자. 

https://school.programmers.co.kr/learn/courses/30/lessons/12913#qna

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

땅따먹기 게임을 하려고 합니다. 땅따먹기 게임의 땅(land)은 총 N 4열로 이루어져 있고, 모든 칸에는 점수가 쓰여 있습니다. 1행부터 땅을 밟으며 한 행씩 내려올 때, 각 행의 4칸 중 한 칸만 밟으면서 내려와야 합니다. , 땅따먹기 게임에는 한 행씩 내려올 때, 같은 열을 연속해서 밟을 수 없는 특수 규칙이 있습니다.

 

예를 들면,

 

| 1 | 2 | 3 | 5 |

 

| 5 | 6 | 7 | 8 |

 

| 4 | 3 | 2 | 1 |

 

로 땅이 주어졌다면, 1행에서 네번째 칸 (5)를 밟았으면, 2행의 네번째 칸 (8)은 밟을 수 없습니다.

 

마지막 행까지 모두 내려왔을 때, 얻을 수 있는 점수의 최대값을 return하는 solution 함수를 완성해 주세요. 위 예의 경우, 1행의 네번째 칸 (5), 2행의 세번째 칸 (7), 3행의 첫번째 칸 (4) 땅을 밟아 16점이 최고점이 되므로 16 return 하면 됩니다.

 

제한사항

  행의 개수 N : 100,000 이하의 자연수

  열의 개수는 4개이고, (land) 2차원 배열로 주어집니다.

  점수 : 100 이하의 자연수

 

문제 해결 방법

 

DP를 활용하여 문제를 풀었음.

두번째 행 기준에서 첫번째 행에서 어느 열부터 출발하냐에 따라 두번째 행에서 시작하는 점수가 달라진다. 

첫번째 행에서 밟을 수 있는 모든 열을 기준으로, 두번째 행에서 밟을 수 있는 열을 밟아서, 두번째 행에서 시작할 수 있는 모든 점수 중 가장 큰 점수를 각 열에 기록했다. 그 다음 행도 이런식으로 점수를 기록한 후, 맨 마지막 행에서 최대 점수를 찾아서 리턴했다. 

 

 

코드 구현

 

DP로 구현한 코드

import copy
def solution(land):
    answer = 0
    
    lenL = len(land)
    originLand = copy.deepcopy(land)
    
    for j in range(0, lenL):
        if j + 1 == lenL:
            break
        
        for i in range(4):
            for k in range(4):
                if i !=k:
                    if land[j+1][k] < originLand[j+1][k] + land[j][i]:
                        land[j+1][k] = originLand[j+1][k] + land[j][i]
                    #print(land)
    answer = (max(land[-1]))
    

    return answer

 

 

DFS(재귀)로 구현후, 간단한 테스트케이스는 통과가 되지만, 제출시 시간초과와 런타임에러로 도배됐던 코드 

def solution(land):
    answer = 0

    check = [False] * 4
    
    #print(land[0])
    
    summ = 0
    maxValue = 0
    maxCnt = len(land)
    cnt = 0
    result = []
    def dfs(check, summ, cnt, result, rem):
        if cnt == maxCnt:
            
            result.append(summ)
            return
        originRem = rem
        for idx, i in enumerate(land[cnt]):
            #print(check, 'rem', rem)
            if check[idx] == True:
                continue
            elif check[idx] == False:
                summ +=i
                check = [False] * 4
                check[idx] = True
                cnt +=1
                # print('cnt',cnt, 'idx', idx, 'i', i, check, 'rem', rem)
                # print()
                rem = idx
                dfs(check, summ, cnt, result, rem)
                check[idx] = False
                check[originRem] = True
                rem = originRem
                summ -=i
                cnt -=1
    
    rem = 0
    for idx, i in enumerate(land[0]):
        summ += i
        check[idx] = True
        cnt +=1
        #print('cnt',cnt, 'i', i)
        rem = idx
        dfs(check, summ, cnt, result, rem)
        check[idx] = False
        summ -=i
        cnt -= 1
            
#     print(result)
#     print(max(result))
            
    answer = max(result)
    return answer

 

 

시간/공간 복잡도

 

 

최악의 경우 O(NlogN)

 

 

최적화 및 개선 / 어려웠던 점

 

내 기준에서 진짜 어려운 문제다. 역대급 어려웠다. 

DP문제는 직관적으로는 이해가 가는데, 코드 구현을 하려고 하니 너무 헷깔리는 부분이 많았다. 

 

그리고 처음부터 이 문제는 문제의 제한사항을 안보고(시간 복잡도를 고려하지 않고) 문제를 풀었었는데, 어떤 문제라도 시간 복잡도를 잘 고려하고 문제에 접근하는 것의 중요성을 아주 많이 느꼈다. 

 

아예 시간복잡도 별 알고리즘과 최대 연산 횟수를 포스트잇에 써서 컴퓨터 본체에 붙여놨다 

 

문제가 어렵긴한데 풀고나니 해방감이 아주 좋고, 즐거움이 느껴진다. 

 

그리고 다른사람이 이 문제에 대해서 상세히 풀이해준 글을 봤는데 처음에 글을 보고도 이해가 잘 안갔다. 

그림으로 그려보기도 했는데 이해가 잘 안갔다. 

 

다시 글을 이해하려고 했을때는 그림을 아주 상세하게 그려서 펼쳐놓고 고민을 많이 하고 해설을 읽어보고를 반복했는데, 

이해가 됐다. 

 

이해가 안되는 문제에 대해서 그림을 상세하게 그리는게 시간이 많이 들진 몰라도, 확실히 그림을 대충그리는 것보다 상세히 그리는게 도움이 많이 되는것 같다. 

 

그리고 내가 작성한 코드에 대해서 시간복잡도를 계산하는 방법을 다시 공부해야할 것 같은 느낌이 든다.

 

 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

양의 정수 n이 주어집니다. 이 숫자를 k진수로 바꿨을 때, 변환된 수 안에 아래 조건에 맞는 소수(Prime number)가 몇 개인지 알아보려 합니다.

 

0P0처럼 소수 양쪽에 0이 있는 경우

P0처럼 소수 오른쪽에만 0이 있고 왼쪽에는 아무것도 없는 경우

0P처럼 소수 왼쪽에만 0이 있고 오른쪽에는 아무것도 없는 경우

P처럼 소수 양쪽에 아무것도 없는 경우

, P는 각 자릿수에 0을 포함하지 않는 소수입니다.

예를 들어, 101 P가 될 수 없습니다.

 

예를 들어, 437674 3진수로 바꾸면 211020101011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 왼쪽부터 순서대로 211, 2, 11이 있으며, 3개입니다. (211, 2, 11 k진법으로 보았을 때가 아닌, 10진법으로 보았을 때 소수여야 한다는 점에 주의합니다.) 211 P0 형태에서 찾을 수 있으며, 2 0P0에서, 11 0P에서 찾을 수 있습니다.

 

정수 n k가 매개변수로 주어집니다. n k진수로 바꿨을 때, 변환된 수 안에서 찾을 수 있는 위 조건에 맞는 소수의 개수를 return 하도록 solution 함수를 완성해 주세요.

 

문제 해결 방법

 

주어진 값을 n진수의 값으로 변환하기 위해서 divmod함수를 사용하여 나머지 값을 모아 하나의 문자열 형태로 만든뒤, 뒤집어줬다. 

해당 문자열에서 소수로 판단할 수를 하나의 리스트에 담아 모아주었다. 

 

해당 리스트의 값을 대상으로 소수를 판별하고 값을 리턴했다. 

 

 

코드 구현

 

from collections import deque
def solution(n, k):
    answer = 0
    strr = ''
    
    # n진수 -> n진수로 변환법
    while n > 0:
        n, mod = divmod(n, k)
        strr += str(mod)

    # 문자열에서 소수 조건에 맞는 수 세아리기 
    
    strr = strr[::-1]
    strr = list(strr)
    
    checkList = []
    
    tmp = ''
    cnt = 0
    for idx, i in enumerate(strr):
        if i !='0':
            tmp+=str(i)
            cnt+=1
            if idx == len(strr)-1:
                checkList.append(tmp)
        else:
            while cnt > 0:
                checkList.append(tmp)
                cnt=0
            
            tmp=''
            cnt = 0
            
    for i in checkList:
        if i == '1':
            continue
     
        cnt = 0
        
        for k in range(2, int((int(i) ** 0.5)+1)):
            if int(i) % k == 0:
                cnt +=1
        
        if cnt == 0:
            answer+=1
    
    return answer

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 / 어려웠던 점

 

주어진 값을 n진수로 변환할 때 코드를 통한 변환 방법을 까먹어서 다시 찾아봤고, 

문자열을 쉽게 뒤집는 방법을 알게됐다. 

 

주어진 값에 대해 소수판별을 하기 위해서 에라토스테네스의 채 방법을 사용했는데, 두개의 테스트케이스에서 자꾸 시간초과가 났다. 해당 방법을 사용할 수 없었다. 

 

소수판별을 해야하는 값들 중에서 가장 긴 값의 범위 만큼만 에라토스테네스의 채 방법을 사용해서 코드를 작성해봤지만, 그 역시도 시간 초과가 났다. 해당 방법을 사용할 수 없었다. 

 

아예 에라토스테네스의 채 방법을 사용하지 않고, 바로바로 소수 판별을 하는게 나으려나 싶어서 아래와 같은 방식을 사용했었다. 

 

from collections import deque
def solution(n, k):
    answer = 0
    strr = ''
    
    # n진수 -> n진수로 변환법
    while n > 0:
        n, mod = divmod(n, k)
        strr += str(mod)

    # 문자열에서 소수 조건에 맞는 수 세아리기 
    
    strr = strr[::-1]
    
    strr = list(strr)
    
    checkList = []
    
    tmp = ''
    cnt = 0
    for idx, i in enumerate(strr):
        if i !='0':
            tmp+=str(i)
            cnt+=1
            if idx == len(strr)-1:
                checkList.append(tmp)
                
        else:
            while cnt > 0:
                checkList.append(tmp)
                cnt=0
            
            tmp=''
            cnt = 0
    #print('checkList', checkList)
    for i in checkList:
        #print(i, answer)
        if i == '1':
            continue
        
        if i == '2' or i == '3' or i == '5' or i == '7':
            
            answer+=1
        else:
            if int(i) % 2 == 0: 
                continue
            if int(i) % 3 == 0: 
                continue
            if int(i) % 5 == 0: 
                continue
            if int(i) % 7 == 0: 
                continue
            if int(i) % (int(i) ** 0.5) == 0:
                continue
            
            #print('check', i)
            answer+=1
            
        #print(i, answer)
    
    return answer

 

처음에는 2, 3, 5, 7의 배수만 거르면 나머지는 다 소수라고 생각했었는데, 2, 3, 5, 7이상의 소수의 배수의 소수가 아닌 값을 고려하지 못했다. (ex. 121) 그래서 그런 값들을 고려하기 위해서 제곱근을 활용했다. 

제곱근을 코드로 구현하는 방법을 몰라서 해당 부분도 찾아봤다. 

 

그런데 저 코드로는 2, 3, 5, 7 이상의 값중 소수인 값을 체크할 수가 없었다. 

 

소수는 1과 자기자신으로만 나눠지는 값이고, 만약 소수가 아니라면 1과 자기자신의 값 사이에 있는 값으로 나눠져야한다. 

 

예를들어서 특정 값이 있을때, 그 값이 소수라면, 약수는 1과 자기자신뿐이다. 만약 소수가 아니라면, 약수는 1과 자기자신 그리고 자기자신의 제곱근과 그 제곱근을 기준으로 작은 약수와 큰 약수가 생긴다. 

 

이 점을 활용해서, 특정 값이 소수임을 판별할때, 1부터 자기자신의 제곱근 사이에 있는 모든 숫자를 가지고 자기자신이 0으로 나눠떨어지는지 확인하면 굳이 큰 약수를 확인하지 않아도 작은 약수임을 확인하는 것 만으로도 특정 값이 소수인지 확인할 수 있게된다. 

 

 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

 

캐시

 

지도개발팀에서 근무하는 제이지는 지도에서 도시 이름을 검색하면 해당 도시와 관련된 맛집 게시물들을 데이터베이스에서 읽어 보여주는 서비스를 개발하고 있다.

이 프로그램의 테스팅 업무를 담당하고 있는 어피치는 서비스를 오픈하기 전 각 로직에 대한 성능 측정을 수행하였는데, 제이지가 작성한 부분 중 데이터베이스에서 게시물을 가져오는 부분의 실행시간이 너무 오래 걸린다는 것을 알게 되었다.

어피치는 제이지에게 해당 로직을 개선하라고 닦달하기 시작하였고, 제이지는 DB 캐시를 적용하여 성능 개선을 시도하고 있지만 캐시 크기를 얼마로 해야 효율적인지 몰라 난감한 상황이다.

 

어피치에게 시달리는 제이지를 도와, DB 캐시를 적용할 때 캐시 크기에 따른 실행시간 측정 프로그램을 작성하시오.

 

 

문제 해결 방법

deque를 사용하여 문제를 해결했다. 

 

LRU 란?
LRU(Least Recently Used)는 가장 오랫동안 참조되지 않은 페이지를 교체하는 방식이다. 
많이 나온 횟수와는 상관 없이 최근(cache size 이내)에 나오지 않았다면 삭제한다.
사용된지 가장 오래된 페이지는 앞으로도 사용될 확률이 낮다는 가설에 의해 만들어진 알고리즘이다.

 

Cache Hit : CPU 가 참조하고자 하는 메모리가 캐시에 존재하고 있을 경우를 말한다. 
Cache Miss : CPU 가 참조하고자 하는 메모리가 캐시에 존재하지 않을 경우를 말한다. 

 

코드 구현

from collections import deque
def solution(cacheSize, cities):
    answer = 0
    
    cache = deque(maxlen=cacheSize)

    for i in cities:
        i=i.lower()
        if i in cache:
            cache = list(cache)

            indexx = cache.index(i)
            
            del cache[indexx]
            cache = deque(cache, maxlen=cacheSize)
            
            cache.append(i)
            answer +=1
        else:
            answer +=5
            cache.append(i)
             
    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 / 어려웠던 점

 

따로 하지않았음.

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

정수 n, left, right가 주어집니다. 다음 과정을 거쳐서 1차원 배열을 만들고자 합니다.

 

n n열 크기의 비어있는 2차원 배열을 만듭니다.

i = 1, 2, 3, ..., n에 대해서, 다음 과정을 반복합니다.

1 1열부터 i i열까지의 영역 내의 모든 빈 칸을 숫자 i로 채웁니다.

1, 2, ..., n행을 잘라내어 모두 이어붙인 새로운 1차원 배열을 만듭니다.

새로운 1차원 배열을 arr이라 할 때, arr[left], arr[left+1], ..., arr[right]만 남기고 나머지는 지웁니다.

정수 n, left, right가 매개변수로 주어집니다. 주어진 과정대로 만들어진 1차원 배열을 return 하도록 solution 함수를 완성해주세요.

 

 

문제 해결 방법

 

2차원 배열 특정 위치에 해당되는 첨자 같은 공식이라고 있었다. 

 

행첨자는 ([현 위치]) / (전체 열의 수 )

열 첨자는 ([현 위치]) % (전체 열의 수)  

 

이거랑 코드 구현의 아이디어랑 관련이 있다. 

 

왜냐하면 문제의 제한사항을 감안하고 구현하려면 left부터 right 까지의 값을 가진 배열을 바로 구해야(left이전의 값이나 right이후의 값을 계산하면 시간초과 이슈 발생)한다. 

 

해당 배열을 바로 구하기 위해서는 문제에서 제공한 행과 열에 대한 값의 관계를 생각해서 행첨자와 열첨자를 이용해 문제를 풀어야만 한다. 

 

행과 열 첨자를 구하면 두 값중 큰 값이 해당 위치의 원소의 값이 된다. 

 

코드 구현

 

def solution(n, left, right):
    answer = []
    for i in range(left,right+1):
        
        a = (i // n) +1# 몫 행첨자 
        b = (i % n) +1#나머지  열 첨자 
        print('a', a, 'b', b)
        if a < b :
            print('check')
            a, b = b, a
        answer.append(a)

    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 / 어려웠던 점

 

진짜 굉장히 어렵다고 생각하는 문제다.

 

처음에 2중 반복문으로 풀었는데 테스트케이스 대부분 시간초과 났따. 그래서 반복문을 하나로 줄였는데도 비슷했다. 

 

굉장히 어렵다고 생각한다. 내가 뭘 모르는건가?

 

그래서 진짜 끙끙 앓다가 힌트랑 남의 코드 봤다. 보고도 이해가 안갔다. 진짜 내가 뭘 모르는게 분명하다. 

 

찾아보니 2차원 배열 특정 위치에 해당되는 첨자 같은 공식을 참고해서 풀었다. 

 

확실히 나는 해당 개념을 몰랐다. 그래서 문제 풀때도 아이디어를 거의 없는걸 창조해서 풀듯이 했고, 남의 코드를 봐도 

 

이해를 잘 못했던 것 같다. 

 

글로 쓰고나니 별거아닌거 같은 이 느낌은 뭐지 ;;; 휴,, 거진 서너시간은 날린 것 같다. 

 

그래도 좋은 경험이였다. 

 

https://school.programmers.co.kr/learn/courses/30/lessons/131701#qna

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

 

철호는 수열을 가지고 놀기 좋아합니다. 어느 날 철호는 어떤 자연수로 이루어진 원형 수열의 연속하는 부분 수열의 합으로 만들 수 있는 수가 모두 몇 가지인지 알아보고 싶어졌습니다. 원형 수열이란 일반적인 수열에서 처음과 끝이 연결된 형태의 수열을 말합니다. 예를 들어 수열 [7, 9, 1, 1, 4] 로 원형 수열을 만들면 다음과 같습니다.

 

 

 

원형 수열은 처음과 끝이 연결되어 끊기는 부분이 없기 때문에 연속하는 부분 수열도 일반적인 수열보다 많아집니다.

원형 수열의 모든 원소 elements가 순서대로 주어질 때, 원형 수열의 연속 부분 수열 합으로 만들 수 있는 수의 개수를 return 하도록 solution 함수를 완성해주세요.

 

문제 해결 방법

 

deque의 maxlen 속성을 이용하여 문제를 해결했다. 

deque의 maxlen 속성은 deque를 생성할때 maxlen에 값을 주면 해당 값만큼의 크기의 deq를 만들 수 있는 속성이다. 

 

만약 사용자가 해당 deque에 maxlen이상의 값을 추가하면 deq에 있는 맨 왼쪽의 값부터 삭제한다. 

(appendleft()를 할 경우, 맨 오른쪽의 원소가 삭제되고 맨 왼쪽에 값이 추가됨)

 

문제에서는 연속된 값의 길이가 1부터 elements의 크기 까지일 수 있다. 

따라서 해당 경우를 헤아려 가며 deq를 만들어주고 deq 요소의 값을 합해준 후, 해당 값을 하나의 리스트에 넣었다. 

 

중복값에 대한 처리는 set으로 해줬다. 

 

코드 구현

 

from collections import deque

def solution(elements):
    answer = 0
    a = []
    for i in range(1,len(elements)+1) :
        deq = deque(maxlen=i)
        
        for i in elements * 2 :
            deq.append(i)
            a.append(sum(deq))
            
    
            
        
    
    return len(set(a))

 

 

시간/공간 복잡도

 

최악의 경우 O(N^2)

 

 

최적화 및 개선 / 어려웠던 점

 

사실 이 문제를 3중 for문으로 풀었는데 아니나 다를까, 테스트 케이스 5번부터 끝까지 시간초과가 났다. 

 

근데 아무리 생각해봐도 3중으로 for문을 사용하지 않으면 문제를 풀 수 있는 방법을 떠올릴 수 없었다. 

 

힌트를 얻어 문제를 풀었다. deque에 maxlen이라는 속성이 있는지 처음 알았다. 최고다!

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

효진이는 멀리 뛰기를 연습하고 있습니다. 효진이는 한번에 1, 또는 2칸을 뛸 수 있습니다. 칸이 총 4개 있을 때, 효진이는

(1, 1, 1, 1)

(1, 2, 1)

(1, 1, 2)

(2, 1, 1)

(2, 2)

5가지 방법으로 맨 끝 칸에 도달할 수 있습니다. 멀리뛰기에 사용될 칸의 수 n이 주어질 때, 효진이가 끝에 도달하는 방법이 몇 가지인지 알아내, 여기에 1234567를 나눈 나머지를 리턴하는 함수, solution을 완성하세요. 예를 들어 4가 입력된다면, 5 return하면 됩니다.

 

문제 해결 방법

 

n이 1일때, 2일때, 3일때, 4일때의 결과를 문제에서 찾고, 5일때 결과를 만들어서 보니 피보나치 수열의 형태를 띄었다. 

피보나치 수열을 구현하여 해당문제를 해결했다. 

 

 

코드 구현

 

import itertools

def solution(n):
    answer = 0
    tmp=[0, 1, 1]
    cnt = 3
    summ = 0
    while 1:
        if n == 1:
            answer = 1
            return answer % 1234567
        elif n == 2:
            answer = 2
            return answer % 1234567
        else:
            summ = (tmp[cnt-1] + tmp[cnt-2]) 
            tmp.append(summ)
            cnt+=1
        
        if cnt == n+2:
            return summ % 1234567
    
    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 / 어려웠던 점

 

입출력의 경우를 쭉 나열해서 문제를 풀어볼 생각을 못하고, 직접 문제 그대로 구현해보려 했다. 

문제 그대로 구현하니 테스트케이스 2번부터 끝까지 시간초과가 났다. 

아무리 생각해봐도 이중 반복문을 사용하지 않고 문제를 해결할 방법이 생각나지 않아서, 힌트를 봤다. 

 

문제가 안풀리면 입출력문을 문제에서 제시한 부분을 나열해보고 그다음 부분은 직접 경우의 수를 구해 붙인뒤에 

점화식을 세워 문제를 풀 생각을 해봐야겠다. 

 

문제에 거의 점화식이 주어지는 경우도 있으니, 이런 부분 감안해서 문제를 읽어볼 것.

 

https://school.programmers.co.kr/learn/courses/30/lessons/12980#qna

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

OO 연구소는 한 번에 K 칸을 앞으로 점프하거나, (현재까지 온 거리) x 2 에 해당하는 위치로 순간이동을 할 수 있는 특수한 기능을 가진 아이언 슈트를 개발하여 판매하고 있습니다. 이 아이언 슈트는 건전지로 작동되는데, 순간이동을 하면 건전지 사용량이 줄지 않지만, 앞으로 K 칸을 점프하면 K 만큼의 건전지 사용량이 듭니다. 그러므로 아이언 슈트를 착용하고 이동할 때는 순간 이동을 하는 것이 더 효율적입니다. 아이언 슈트 구매자는 아이언 슈트를 착용하고 거리가 N 만큼 떨어져 있는 장소로 가려고 합니다. , 건전지 사용량을 줄이기 위해 점프로 이동하는 것은 최소로 하려고 합니다. 아이언 슈트 구매자가 이동하려는 거리 N이 주어졌을 때, 사용해야 하는 건전지 사용량의 최솟값을 return하는 solution 함수를 만들어 주세요.

 

예를 들어 거리가 5만큼 떨어져 있는 장소로 가려고 합니다.

아이언 슈트를 입고 거리가 5만큼 떨어져 있는 장소로 갈 수 있는 경우의 수는 여러 가지입니다.

 

처음 위치 0 에서 5 칸을 앞으로 점프하면 바로 도착하지만, 건전지 사용량이 5 만큼 듭니다.

처음 위치 0 에서 2 칸을 앞으로 점프한 다음 순간이동 하면 (현재까지 온 거리 : 2) x 2에 해당하는 위치로 이동할 수 있으므로 위치 4로 이동합니다. 이때 1 칸을 앞으로 점프하면 도착하므로 건전지 사용량이 3 만큼 듭니다.

처음 위치 0 에서 1 칸을 앞으로 점프한 다음 순간이동 하면 (현재까지 온 거리 : 1) x 2에 해당하는 위치로 이동할 수 있으므로 위치 2로 이동됩니다. 이때 다시 순간이동 하면 (현재까지 온 거리 : 2) x 2 만큼 이동할 수 있으므로 위치 4로 이동합니다. 이때 1 칸을 앞으로 점프하면 도착하므로 건전지 사용량이 2 만큼 듭니다.

위의 3가지 경우 거리가 5만큼 떨어져 있는 장소로 가기 위해서 3번째 경우가 건전지 사용량이 가장 적으므로 답은 2가 됩니다.

 

문제 해결 방법

 

N을 2로 나눌때 나눠 떨어지면 넘어가고 2로 나눠떨어지지 않을때 ans를 1씩 추가한다. 

만약 n이 1까지 도달하면 ans를 1 추가하고 ans를 리턴한다. 

 

문제에서 한번 점프할때 1칸, 2칸 혹은 N칸 간격 까지 할 수 있지만, 문제에서 제시한 설명처럼 1칸 점프하는게 효율적임을 알 수 있다. 따라서 점프는 1칸만 하는 경우만 고려한다. 

 

 

코드 구현

 

def solution(n):
    ans = 0
    
    
    while 1:
        if n == 1:
            ans+=1
            break
        
        if n % 2 == 0 :
            n = n // 2
        else:
            n = n - 1
            ans += 1
        
    
    return ans

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 및 어려웠던 점

 

사실 이 문제 도저히 못풀겠어서 힌트를 참고했다. 


이런 식의 문제는 0에서 N으로 가는 코드를 작성할때보다.

N부터 시작해서 0 으로 갈때에 해결되는 경우가 많이 나오는 것을 힌트로 알게되었다. 

 

현재까지 온 거리가 2의 배수가 되므로 2로 나눠야 되는 것을 알게되었다.  만약 나눠떨어 지지 않으면 점프를 해야한다. 

(점프를 하면 1칸만 이동할 수 있으므로)

 

아직 이 문제가 직관적으로 와닿지 않는다.

이런 유형의 문제도 좀 많이 풀어봐야겠다. 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

얀에서는 매년 달리기 경주가 열립니다. 해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때 추월한 선수의 이름을 부릅니다. 예를 들어 1등부터 3등까지 "mumu", "soe", "poe" 선수들이 순서대로 달리고 있을 때, 해설진이 "soe"선수를 불렀다면 2등인 "soe" 선수가 1등인 "mumu" 선수를 추월했다는 것입니다. "soe" 선수가 1, "mumu" 선수가 2등으로 바뀝니다.

 

선수들의 이름이 1등부터 현재 등수 순서대로 담긴 문자열 배열 players와 해설진이 부른 이름을 담은 문자열 배열 callings가 매개변수로 주어질 때, 경주가 끝났을 때 선수들의 이름을 1등부터 등수 순서대로 배열에 담아 return 하는 solution 함수를 완성해주세요.

 

 

 

문제 해결 방법

 

 

이문제 진짜 딕셔너리 순환을 위해서 이중 for문을 사용하지 않고, 하나의 반복문만 사용하고,

더이상의 반복문을 사용하지 않기 위해서, 딕셔너리 두개로 선수의 순위를 바로바로 바꿔주었다. 

 

 

코드 구현

 

def solution(players, callings):
    answer = []
    
    dicct={}
    dic={}
    for idx, i in enumerate(players):
        dicct[i]=idx
    
    for idx, i in enumerate(players):
        dic[idx]=i
        
    
    
    
#     print('dic', dic) # key는 숫자 
#     print('dicct', dicct) # key는 이름 
    
    for i in callings:
        value = dicct[i] # 숫자
        key = dic[value]
        
        value2 = dicct[i]-1
        key2 = dic[value2]
        
        
        dic[value] = key2
        dicct[key] = value2
        
        dic[value2] = key
        dicct[key2] = value
    
    for key, value in dic.items():
        answer.append(value)
    
    return answer

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선

시간초과가 났다. 

딕셔너리 전체 순환을 하면 안되나보다.

딕셔너리 두개로 반복문 하나만 사용해서 문제를 풀었다. 

하나의 딕셔너리로 key를 통한 검색을 위해 도중에 key와 value를 바꿔주고자 했지만, 해당 방법을 사용하면 또 반복문을 사용해야 해서 해당 방법은 사용할 수 없었다. 

 

 

어려웠던 점

 

막상 풀고보니 전체 순환을 안할 수 있다는게 넘 신기하다. 

 

+ Recent posts