문제출처 : 프로그래머스 모의테스트 페이지
https://programmers.co.kr/learn/courses/18
파트1. 자릿수 더하기 문제
https://programmers.co.kr/learn/courses/18/lessons/1876
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import Foundation
func solution(_ n:Int) -> Int
{
var answer:Int = 0
let input = String(n)
for c in input {
answer += Int(String(c))!
}
// 또는
// answer = input.map({ Int(String($0))! }).reduce(0) { $0 + $1 }
return answer
}
|
파트2. 순열 검사 문제
https://programmers.co.kr/learn/courses/18/lessons/1877
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import Foundation
func solution(_ arr:[Int]) -> Bool {
var answer = true
// 빠른 탐색을 위해 배열을 정렬
let newArr = arr.sorted()
for i in 0..<newArr.count {
// 중간에 false가 뜨면 더 이상 탐색하지 않고 종료
if answer == false {
break
}
// contains는 느리므로 배열값을 i와 바로 비교
if newArr[i] != (i + 1) {
answer = false
}
}
return answer
}
|
파트3. 나머지 한 점 문제
https://programmers.co.kr/learn/courses/18/lessons/1878
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
import Foundation
func solution(_ v: [[Int]]) -> [Int]
{
var answer = [Int]()
let setA = v[0]
let setB = v[1]
let setC = v[2]
// A와 B가 같으면 D는 C와 동일
// A와 C가 같으면 D는 B와 동일
// 같은게 없으면 D는 A와 동일
// 앞의 점 구하기
if (setA[0] == setB[0]) {
answer.append(setC[0])
} else if (setA[0] == setC[0]) {
answer.append(setB[0])
} else {
answer.append(setA[0])
}
// 뒤의 점 구하기
if (setA[1] == setB[1]) {
answer.append(setC[1])
} else if (setA[1] == setC[1]) {
answer.append(setB[1])
} else {
answer.append(setA[1])
}
return answer
}
|
파트4. 가장 큰 정사각형 찾기 문제
https://programmers.co.kr/learn/courses/18/lessons/1879
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
import Foundation
func solution(_ board:[[Int]]) -> Int
{
var newBoard = board
let row = newBoard.count
let col = newBoard[0].count
var answer = 0
// 행이나 열의 길이가 2 미만이라면 직접 돌리면서 1이 하나라도 있는지 체크
// 하나라도 있으면 통과.
if (col < 2 || row < 2) {
for i in 0 ..< row {
for j in 0 ..< col {
if newBoard[i][j] == 1 {
answer = 1
}
}
}
} else {
// 배열의 [1][1]부터 반복문을 돌린다. (첫 번째 행, 첫 번째 열 무시)
// 현재 값이 1일 경우, 좌측값, 상단값, 좌측상단값 중
// 가장 작은 값의 +1 한 값을 현재 값으로 할당
for i in 1 ..< row {
for j in 1 ..< col {
if newBoard[i][j] == 1 {
newBoard[i][j] = min(newBoard[i - 1][j], newBoard[i][j - 1], newBoard[i - 1][j - 1]) + 1
if newBoard[i][j] > answer {
answer = newBoard[i][j]
}
}
}
}
}
return answer - answer
}
|
파트5. 땅따먹기 문제
https://programmers.co.kr/learn/courses/18/lessons/1880
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import Foundation
func solution(_ land:[[Int]]) -> Int{
var answer = 0
var newLand = land
for i in 1 ..< newLand.count {
newLand[i][0] += max(newLand[i - 1][1], newLand[i - 1][2], newLand[i - 1][3])
newLand[i][1] += max(newLand[i - 1][0], newLand[i - 1][2], newLand[i - 1][3])
newLand[i][2] += max(newLand[i - 1][0], newLand[i - 1][1], newLand[i - 1][3])
newLand[i][3] += max(newLand[i - 1][0], newLand[i - 1][1], newLand[i - 1][2])
}
answer = (newLand.last?.max())!
return answer
}
|
파트6. 스티커 모으기 문제
https://programmers.co.kr/learn/courses/18/lessons/1881
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
import Foundation
func solution(_ sticker:[Int]) -> Int{
// 예외처리
if sticker.count == 0 { return 0 }
if sticker.count == 1 { return sticker[0] }
var dp1 = [Int]() // 첫번째 뜯은 경우
var dp2 = [Int]() // 첫번째 안뜯은 경우
// 첫번째 뜯은 경우 첫번째는 스티커값
dp1.append(sticker[0])
dp1.append(dp1[0])
// 첫번째 안뜯은 경우 첫번째는 0, 두번째는 스티커값
dp2.append(0)
dp2.append(sticker[1])
// 스티커가 원형인걸 반영하기 위해 탐색범위를 다르게 함
if sticker.count > 2 {
// 첫번째를 뜯었으면 n-1을 뜯으면 안되므로 n-2까지 탐색
for i in 2 ... sticker.count - 2 {
// 하나 건너뛰어서 스티커를 떼는게 나은지 다음 스티커를 기다릴지 판정
let value = max(dp1[i-2] + sticker[i], dp1[i-1])
dp1.append(value)
}
// n-1까지 탐색
for i in 2 ... sticker.count - 1 {
let value = max(dp2[i-2] + sticker[i], dp2[i-1])
dp2.append(value)
}
}
return max(dp1.max()!, dp2.max()!)
}
|
파트7. 단어 퍼즐 문제
https://programmers.co.kr/learn/courses/18/lessons/1882
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
import Foundation
func solution(_ strs:[String], _ t:String) -> Int {
let INF = 9999
let wordLength = t.count
// 고속탐색을 위한 해시셋 생성
let strsSet = Set(strs.map { $0 })
// 고속탐색을 위한 스트링셋 생성
let splitT = t.map { String($0) }
// 각 자리에서 사용가능한 단어조각 최소값 저장을 가장 큰값으로 저장한 배열을 생성
// dp[i] = min(dp[i+1],dp[i+2],dp[i+3],dp[i+4]) + 1
var dp = [Int](repeating: INF, count: wordLength)
dp.append(0)
// 각자리별로 사용 가능한 단어조각의 최소값을 뒷자리부터 계산
for i in (0 ..< wordLength).reversed() {
// 단어조각 최대 길이는 5
for j in 0 ..< 5 {
let k = i + j + 1
// 검색 인덱스를 넘어가면 종료
if k > wordLength {
break
}
// 사용가능한 단어가 있는지 확인
// Swift의 String.index는 쓰기는 편하지만 매우 느리다
// let availWord = String(t[t.index(t.startIndex, offsetBy: i)..<t.index(t.startIndex, offsetBy: k)])
// 그래서 단어매치를 할땐 배열로 직접 가져와서 해시셋과 비교해야 된다
// strsSet과 비교할 단어를 생성
var availWord = String()
for idx in i ..< k {
availWord += splitT[idx]
}
// 조합이 가능하면 dp[i]의 값을 최소값으로 갱신
if (strsSet.contains(availWord) && dp[i + j + 1] != INF) {
dp[i] = min(dp[i], dp[i + j + 1] + 1)
}
}
}
// 단어를 조합해서 만들 수 없으면 -1 반환, 아니면 dp[0] 반환
if dp[0] == INF { return -1 }
return dp[0]
}
|