▼ 문제 링크
StoneWall coding task - Learn to Code - Codility
Cover "Manhattan skyline" using the minimum number of rectangles.
app.codility.com
영어로 된 문제가 너무 난해해서 이해하기 너무 어려웠던 문제.(사실 아직도 문제는 무슨 소린지 모르겠음;;) 벽돌을 쌓네 마네 하는 것들은 일단 뒤로 재쳐두고, 주어진 배열만 보고 유추해서 풀었다.
# 풀이 1
FIFO Queue를 이용한 풀이
import Foundation
import Glibc
public func solution(_ H : inout [Int]) -> Int {
var count = 0
// use queue
while !H.isEmpty {
count += 1
var index = 0
let value = H.removeFirst()
while index < H.count && value <= H[index] {
H[index] -= value
index += 1
}
// 0인 요소를 제외하되, 가장 첫번째 요소부터 연속된 0만 제외
while !H.isEmpty {
if H.first == 0 {
H.removeFirst()
} else {
break
}
}
}
return count
}
swift
First-In First-Out, 선입선출의 특징을 가진 Queue를 이용한 풀이.
1. 배열의 첫 요소를 추출해서 value에 담는다.
2. value보다 크거나 같은 연속된 요소들을 찾아 value값 만큼 빼준다.
3. 배열 H의 첫 요소가 0으로 시작하면 해당 요소를 아예 제거해준다.
4. 배열 H가 빌때까지 1~3번 과정을 반복한다.
반복한 횟수가 count, 즉 문제에서 말하는 가장 최소로 필요한 벽돌의 개수가 된다.
테스트 케이스를 통과해서 맞겠거니 했는데... 퍼포먼스 테스트에서 죄다 탈락했다. 🥲

퍼포먼스를 조금이라도 향상시켜보고자 첫번째 요소가 아니라 마지막 요소를 사용해보기로 했다. (배열에서 맨 뒤가 아닌 중간 요소를 제거하면 해당 요소 뒤에 위치한 모든 요소들의 위치를 재정렬해줘야하기 때문에)
# 풀이 2
removeFirst() 대신 removeLast()
import Foundation
import Glibc
public func solution(_ H : inout [Int]) -> Int {
var count = 0
// use queue
while !H.isEmpty {
count += 1
let value = H.removeLast()
var index = H.count-1
while index >= 0 && value <= H[index] {
H[index] -= value
index -= 1
}
// 0인 요소를 제외하되, 가장 첫번째 요소부터 연속된 0만 제외
while !H.isEmpty {
if H.last == 0 {
H.removeLast()
} else {
break
}
}
}
return count
}
swift
배열 H의 첫번째 요소가 아니라 마지막 요소를 사용하는 걸 제외한 전체적 로직은 풀이 1과 동일하다.
솔직히 퍼포먼스가 많이 개선됐을 거라고는 기대 안했는데, 그래서 그런지 결과도 딱 그만큼 나왔다.

(심지어 Wrong Answer의 값도 풀이 1과 2가 다르다 🙃)
아무리 생각해도 답이 안나와 결국 집단지성의 힘을 빌렸다.
# 풀이 3
LIFO Stack을 이용한 풀이
import Foundation
import Glibc
public func solution(_ H : inout [Int]) -> Int {
var count = 0
var stack = [Int]()
// use stack
for value in H {
while stack.count > 0 && stack.last! > value {
stack.removeLast()
}
if stack.count == 0 || stack.last! < value {
stack.append(value)
count += 1
}
}
return count
}
swift
나는 풀이 1과 풀이 2를 Queue를 사용해서 풀었는데, 사실 정답은 Stack이었다. 😭 위 방법으로 풀면 굳이 요소끼리의 차를 구할 필요도 없고 그저 큰지 작은지 비교만 하면 된다.
1. 쌓을 벽돌(H[i])이 이전 벽돌(stack의 마지막 요소)보다 작으면 이전 벽돌(Stack의 마지막 요소)을 없앤다.
2. 쌓을 벽돌(H[i])보다 작은 벽돌이 나올 때까지 1번을 반복한다.

O(N)의 시간 복잡도로 간단하게 퍼포먼스 테스트도 통과했다.
사실 아직도 풀이 3을 완벽하게 이해하지 못했다. 분명 어려운 문제는 아닌데 문제에 대한 이해가 부족한 것 같다. 좀 더 살펴봐야지.
'Algorithm' 카테고리의 다른 글
[프로그래머스] 멀쩡한 사각형 - 최대공약수 구하기 (0) | 2021.07.27 |
---|---|
[코딜리티] MaxDoubleSliceSum (0) | 2021.07.23 |
[프로그래머스] 정렬 - 가장 큰 수 (0) | 2021.07.11 |
[프로그래머스] 짝지어 제거하기 - 효율성 통과하기 (0) | 2021.06.29 |
[코딜리티] Tape Equilibrium - 시간 복잡도 줄이기 (0) | 2021.06.13 |