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

 

프로그래머스

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

programmers.co.kr


try1

처음에 가장 먼저 떠올리는 간단한 알고리즘으로 테스트를 함

 

※ 나의 코드

def solution(board, skill):
    answer = 0
    
    for sk in skill:                                # 매 skill마다 해당하는 행렬범위에 degree 연산
        for x in range(sk[1], sk[3] + 1):
            for y in range(sk[2], sk[4] + 1):
                if sk[0] == 1:
                    board[x][y] -= sk[-1]
                if sk[0] == 2:
                    board[x][y] += sk[-1]
                    
    for bo in board:
        answer += len([b for b in bo if b > 0])
    
    return answer

문제풀이)

3중 for문으로 매 skill마다 해당 행렬 범위를 board에 type에 따라 degree만큼 더하거나 빼줌

모든 skill이 끝난 후 for문으로 board의 행들을 도는데 행마다 0보다 큰 값을 리스트에 담아 길이를 세서 answer에 더해줌

 

테스트 결과) - 효율성 실패


try2

시간복잡도를 줄일 수 있는 생각이 떠올리지 않아 검색을 함

검색을 해보니 누적합이란 것을 알게 됨

누적합에 대한 이론을 보고 코드로 구현함

 

※ 나의 코드

def solution(board, skill):
    answer = 0

    # 누적합를 위한 보드 acboard
    acboard = [[0] * (len(board[0]) + 1) for _ in range(len(board) + 1)]

    # 누적합 과정
    for ty, r1, c1, r2, c2, degree in skill:
        acboard[r1][c1] += - degree if ty == 1 else degree
        acboard[r1][c2 + 1] += degree if ty == 1 else - degree
        acboard[r2 + 1][c1] += degree if ty == 1 else - degree
        acboard[r2 + 1][c2 + 1] += - degree if ty == 1 else degree

    for y in range(len(acboard[0])):
        for x in range(len(acboard) - 1):
            acboard[x + 1][y] += acboard[x][y]

    for x in range(len(acboard)):
        for y in range(len(acboard[0]) - 1):
            acboard[x][y + 1] += acboard[x][y]

    # board와 acboard를 합침
    for x in range(len(board)):
        for y in range(len(board[0])):
            board[x][y] += acboard[x][y]
            if board[x][y] > 0: answer += 1
    return answer

문제풀이)

누적합 이론

더보기

예를 들어 1차원에서 길이가 5인 [a, b, c, d, e]가 있다고 하고

첫 인덱스가 0이고 0~2번째에 -N만큼 더한다고 하면 3번째에 N을 두고

누적합 배열은 위의 그림과 같은 과정을 거치고 [-N, -N, -N, 0, 0, 0]이 됨

이때 누적합 배열의 길이가 6인 이유는 만약 원래 배열에서 마지막 인덱스까지 -N만큼 더한다고 하면 누적합 배열에서는 그 마지막 인덱스 다음 인덱스에 N을 둬야하기 때문임

 


 

풀려는 문제는 2차원 배열이기 때문에

위의 그림 처럼 N들을 두고 행기준으로 누적합하고 열기준으로 누적합을 해주면 됨(작성한 코드에서는 열기준 -> 행기준)

 

코드를 설명하자면

누적합을 위한 2차원 배열을 위해 전부 값이 0인 상태로 acboard를 만듦

for문으로 매 skill 마다 N을 두는 과정을 거침

다음 for문에서 열기준으로 누적합을 함

다음 for문에서 행기준으로 누적합을 함

마지막 for문에서 board와 acboard를 합치면서 값이 0이상이라면 answer에 1을 더해줌

 

테스트 결과) - 총합 : 정확성 17.61ms,  효율성 5183.71ms

더보기

정확성

테스트 1 통과 (0.02ms, 10.1MB)
테스트 2 통과 (0.11ms, 10.3MB)
테스트 3 통과 (0.37ms, 10.1MB)
테스트 4 통과 (0.43ms, 10.3MB)
테스트 5 통과 (0.75ms, 10.2MB)
테스트 6 통과 (2.11ms, 10.1MB)
테스트 7 통과 (2.77ms, 10.2MB)
테스트 8 통과 (4.01ms, 10.3MB)
테스트 9 통과 (2.82ms, 10.5MB)
테스트 10 통과 (4.22ms, 10.4MB)

 

효율성

테스트 1 통과 (794.67ms, 143MB)
테스트 2 통과 (900.96ms, 143MB)
테스트 3 통과 (797.85ms, 143MB)
테스트 4 통과 (892.60ms, 143MB)
테스트 5 통과 (594.72ms, 132MB)
테스트 6 통과 (625.23ms, 132MB)
테스트 7 통과 (577.68ms, 132MB)

'프로그래머스-파이썬' 카테고리의 다른 글

광고 삽입  (0) 2022.10.18
기둥과 보 설치  (0) 2022.10.12
자물쇠와 열쇠  (1) 2022.09.28
합승 택시 요금  (1) 2022.09.21
양궁대회  (0) 2022.09.14

+ Recent posts