๐ ๋ฌธ์ ๋งํฌ
https://school.programmers.co.kr/learn/courses/30/lessons/17679
๐ ๋์ ํ์ด
1. ์ ๋ ฅ๋๋ board๋ฅผ 2์ฐจ์ ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ
2. 4๊ฐ๊ฐ๋ก ๋ชจ์ฌ์๋ ์ขํ๋ฅผ ํ์, removePoint (์ง์ฐ๋์ขํ) ์งํฉ (set)์ ๋ฃ์ด์ฃผ๊ธฐ
3. removePoint์ ๊ฐ๋ค์ด ๋ค์ด์๋ค๋ฉด, ํด๋น ์ขํ๋ฅผ "-"๋ก ๋ฐ๊พธ์ด ์ญ์ ์ฒ๋ฆฌ & cnt ์ง์ฐ๋ ๋ธ๋ก ๊ฐฏ์ ๋ํด์ฃผ๊ธฐ
4. ์ญ์ ๋ ๋ถ๋ถ ์์์๋ ๋ธ๋ก๋ค ๋ด๋ ค์ฃผ๊ธฐ
4๊ฐ์ ๋ธ๋ก๋ง ํฐ๋จ๋ฆฌ๋ ๊ฒ์ด๋ฏ๋ก, ํ์ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ๋ก ์ฐ์ง ์์๋ค. ๊ทธ๋ฅ ๊ตฌํ์ผ๋ก ๊ฐ๋ฅํ ๊ฒ ๊ฐ์์! ๊ทธ๋ฆผ์ ๊ทธ๋ ค๋ณด๋, ์ง์ฐ๋ ์ขํ๋ ๋ค์๊ณผ ๊ฐ์๋ค.
์ฒซ๋ฒ์งธ ์ฒ๋ผ A๊ฐ ์ฌ์ฏ๊ฐ๊ฐ ์๋๋ผ๋, 4๊ฐ์ฉ ํ์ ํ, ์ค๋ณต๋๋ ์ขํ๋ค์ ์ฒ๋ฆฌํด์ฃผ๋ฉด ๋ ๊ฒ๊ฐ์๋ค. ๊ทธ๋์ '์ง์ฐ๋ ์ขํ๋ค'์ Set์ผ๋ก ๊ตฌ์ฑํ์ฌ ์ฝ๋๋ฅด ์์ฑํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ธ๋ก์ ๋ด๋ ค์ฃผ๋ ๋ก์ง์ ์๋์ ๊ฐ์ด ์๊ฐํ๋ค.
์ ๊ทธ๋ฆฌ๊ณ , ๋ ธ๋์ ํ๊ดํฌ์ผ๋ก ์น ํ ๋ถ๋ถ๋ง ๋ด์ฃผ๋ฉด์ ๋ธ๋ก์ ์ฒ๋ฆฌํ๋ค. (i+1์ด๋ j+1์ด ๋๋ ๋ถ๋ถ์ ๊ตณ์ด for๋ฌธ ๋ฒ์ ๋ด์ ์๋ฃ์ด์ค๋ ๋๊ธฐ ๋๋ฌธ์ด๋ค!
์ฒซ๋ฒ์งธ๋ก ์ง ์ฝ๋๋ ์๋์ ๊ฐ๋ค. ๊ทผ๋ฐ test case 5๋ฒ๊ณผ 10๋ฒ์์ ์คํจ๊ฐ ๋ด๋ค. ์๊ฐ์ด๊ณผ๊ฐ ์๋๊ณ ์คํจ์ธ ์ด์, ์ด๋ค case์์๋ ๋ด ๋ก์ง์ด ์๋ชป๋๊ตฌ๋๋ฅผ ํ์ ํ๋ค.
์คํจ์ฝ๋
//
// main.swift
// Algorithm
//
// Created by LeeJiSoo on 2022/09/03.
//
import Foundation
let m = 4
let n = 5
let board = ["CCBDE", "AAADE", "AAABF", "CCBBF"]
// ๊ฒฐ๊ณผ๊ฐ : 14
func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
// board๋ฅผ 2์ฐจ์ ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ
var newBoard = splitBoard(board)
// ์ง์ฐ๋ ์ขํ๋ฅผ ๊ธฐ๋กํ๊ธฐ ์ํ set ์ค์ & return ๊ฐ ์ค์
var removePoint = Set<[Int]>()
var cnt = 0
// ํ๋ ์ฆ 4๋ธ๋ก์ด ์์ด์ง๋๊น์ง ๋๋ ค์ผํ๋๊น, while ๋ฌธ์ผ๋ก removePoint ์กฐ๊ฑด ๊ฒ์ฌ
// ์๋ while !removePoint.isEmpty ์ ์กฐ๊ฑด์ผ๋ก ์ฃผ์๋๋ฐ, removePoint๋ ๋งค๋ฒ ์ด๊ธฐํํด์ฃผ๋๊น ์ด ์กฐ๊ฑด์ ์๋๋๊ตฌ๋๋ฅผ ๊นจ๋ณ์
while true {
// 4๋ธ๋ก ์์น ์ฐพ์์ removePoint์ ๋ฃ์ด์ฃผ๊ธฐ
for i in 0..<m-1 {
for j in 0..<n-1 {
let point = newBoard[i][j]
// ๋ง์ฝ point ๊ฐ - ๋ผ๋ฉด, ์ด๋ฏธ ์ ๊ฑฐ๋ ์์น์ด๋ฏ๋ก continue
if point == "-" {
continue
}
// ์ฌ๋ฐฉ์ ๋ณด๊ณ ๋ค point ์ ๊ฐ๋ค๋ฉด removePoint์ ํด๋น ์ขํ ์ถ๊ฐ
if newBoard[i][j+1] == point, newBoard[i+1][j] == point, newBoard[i+1][j+1] == point {
removePoint.insert([i, j])
removePoint.insert([i, j+1])
removePoint.insert([i+1, j])
removePoint.insert([i+1, j+1])
}
}
}
// removiPoint๊ฐ ์์ผ๋ฉด cnt ๋ํด์ฃผ๊ณ ๋ธ๋ก ์ง์ฐ๊ณ , ์์ผ๋ฉด ๋ cnt ์ถ๋ ฅ
if !removePoint.isEmpty {
cnt += removePoint.count
for point in removePoint {
newBoard[point[0]][point[1]] = "-"
}
removePoint = Set<[Int]>()
} else {
break
}
// ์ง๊ธ ๋ธ๋ก ์๋ ๊ณณ์ด "-"์ธ๋ฐ, ๋ธ๋ก์ ์ฐจ๋ก๋๋ก ๋ฐ์ผ๋ก ๋ด๋ ค์ค์ผํจ
for i in 0..<m-1 {
for j in 0..<n {
let block = newBoard[i][j]
let under = newBoard[i+1][j]
if under == "-" {
newBoard[i][j] = "-"
newBoard[i+1][j] = block
} else {
continue
}
}
}
}
return cnt
}
func splitBoard(_ board: [String]) -> [[String]] {
var newBoard = [[String]]()
for b in board {
let arr = b.map { String($0) }
newBoard.append(arr)
}
return newBoard
}
print(solution(m, n, board))
์ธํฐ๋ท์ ์ฐพ์๋ณด๋๊น ๋ง์ ์ฌ๋๋ค์ด ๋ค์ํ ์์ธ์ผ๋ก 5๋ฒ๊ณผ 10๋ฒ์ ํต๊ณผํ์ง ๋ชปํ๊ณ ์์๋ค
1. ๊ณต๋ฐฑ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ ํต๊ณผํ์ง ๋ชปํ๋ค๋ ๋ถ
https://lsh424.tistory.com/85
๋๋,, ๊ณต๋ฐฑ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ์์ ํ ํด์ฃผ์๊ณ , ์ด ๋ธ๋ก๊ทธ์์ ์๋ ค์ฃผ๋ ๋ฐ๋ก๋ฅผ ๋์ ํด๋ด๋ ์ ์์ ์ผ๋ก ์๋ํ๋ค. ๋๋ ์ด ์์ธ์ ์๋ ๊ฒ ๊ฐ๋ค.
2. ๋ฐ๋ก ํต๊ณผํ๋์ง ์ดํด๋ณด๊ธฐ + ๋ฐฐ์ด์ ์ฌ๋ฐฐ์น(๋ธ๋ก์ ๋ด๋ฆด๋) ํ ๋ ์๋ชป ํ๋ค๊ณ ํ์๋ ๋ถ
(๋ฐ๋ก์ฐธ๊ณ )https://dev-note-97.tistory.com/105
(๋ธ๋ก๋ด๋ฆด ๋ ์ค๋ฅ๋ผ๊ณ ํ์๋ ๋ถ, ์ฝ๋ ์ฐธ๊ณ ) https://velog.io/@syi07030/Swift-%EA%B3%B5%EB%B6%80-Programmers-1%EC%B0%A8-%ED%94%84%EB%A0%8C%EC%A6%884%EB%B8%94%EB%A1%9D-level2-2018-KAKAO-BLIND-RECRUITMENT
์ด ๋ธ๋ก๊ทธ์์ ์ ์ํ ๋ฐ๋ก๋ฅผ ํต๊ณผํ์ง ๋ชปํ๋ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ๋ค.
// ๋ฐ๋ก
let m = 5
let n = 6
let board = ["AAAAAA","BBAATB","BBAATB","JJJTAA","JJJTAA"]
// ๊ฒฐ๊ณผ๊ฐ : 24
๋๋ถ๋ถ ๋ฐ๋ก๋ฅผ ํต๊ณผํ์ง ๋ชปํ๋ ์ด์ ๋, ๋ธ๋ก์ ๋ด๋ฆด๋ ์๋ชป๋ ๋ก์ง์ผ๋ก ๋ฐ์ํ ๊ฒ ๊ฐ์๋ค. ๊ทธ๋์ ๋ธ๋ก์ ๋ด๋ ค์ฃผ๋ ๋ฐฉ์์ ์์ ํด๋ณด๊ธฐ๋ก ํ๋ค.
๋์ ํ ๋ฌด์จ ์์ธ์ธ์ง ๋ชฐ๋ผ์, ๋ค๋ฅธ ์ฝ๋๋ฅผ ์ฐพ์๋ดค๋ค. removePoint๋ฅผ ์ญ์ ํ๊ณ , ๋ธ๋ก์ ๋ฐ์ผ๋ก ๋ด๋ ค์ฃผ๋ ๊ณผ์ ์์ ๋๋ถ๋ถ์ ์ฌ๋๋ค์ '๊ฑฐ๊พธ๋ก' ์งํํ๋ค. ์ฆ, ๋๋ ์์์๋ถํฐ ์ฐจ๋ก๋๋ก for๋ฌธ์ ๋๋ ค์, ๋ฐ์ "-"๋ฉด, ์๋ ์๋๋ ๋ฐ๊ฟ๋ผ~ ์ด๋ฐ ์์๋ก ์งํํ๋ค. ํ์ง๋ง ์ด๋ ๊ฒ ํ๊ฒ ๋๋ฉด ์๋์ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
์ด๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋ต์ด 24๊ฐ ๋์์ผํ๋ ๋ฐ๋ก์์ 20์ผ๋ก ๋์จ๊ฒ์ด๊ณ , AA,TB๊ฐ ์ ๋๋ก ๋ด๋ ค์ค์ง ์์์ ์ญ์ ๋์ง ์์ 4๊ฐ๊ฐ count ๋์ง ์์๋ค ๊ฒ์ด๋ค.
๊ทธ๋์ ์ฌ๋๋ค์ด for๋ฌธ์ ๋๋ฆด๋, ๋ฐ๋ถ๋ถ ๋ถํฐ ๋๋ ธ๊ตฌ๋,, ๊ทธ๋์ ์ฐธ๊ณ ํ ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
// 5๋ฒ 10๋ฒ ์คํจ ์ฝ๋
// ๋ธ๋ก ๋ด๋ฆฌ๋ ๋ถ๋ถ์ ์ฝ๋
// for i in 0..<m-1 {
// for j in 0..<n {
// let block = newBoard[i][j]
// let under = newBoard[i+1][j]
// if block != "-", under == "-" {
// newBoard[i+1][j] = block
// newBoard[i][j] = "-"
// } else {
// continue
// }
// }
// }
// ์ด๋ ๊ฒ ๋ฐ๊ฟ์ผํ๋ค.
for j in stride(from: 0, to: n, by: 1){ //์ด
var first = 0 //๋ธ๋ก์ด ๋ด๋ ค์์ผํ ํ ์์น
if newBoard[m-1][j] == "-" {
first = m-1
}
for i in stride(from: m-2, through: 0, by: -1){ //ํ
if newBoard[i][j] == "-" {
if i > first {
first = i
}
} else if newBoard[i+1][j] == "-"{
newBoard[first][j] = newBoard[i][j]
newBoard[i][j] = "-"
first -= 1
}
}
}
๋๋์ฒด ์ํ๋ณผ๋ ์ด๋ฐ ๋ฐ๋ก๋ฅผ ์ด๋ป๊ฒ ์๊ฐํ๋ ๋ง์ด๋ค ใ ใ ใ ์์ง ์ค๋ ฅ์ด ๋ง์ด ๋ถ์กฑํ๊ฐ๋ณด๋ค. ์ด๋์ ์คํจ๊ฐ ๋ณ๋์ง ์ ํ ๊ฐ์ ์ก์ง ๋ชปํด์ ์ฌ๋ฌ ์ธํฐ๋ท์ ์ฐธ๊ณ ํด๋ดค๋ค. ๋ค๋ค ์ ์ฒ์ฌ๊ฐ์ง?
์ฆ, ๊ฐ์ฅ ์ค์ํ ๊ฒ์, ๋ธ๋ก์ ์๋๋ก ๋ด๋ฆฌ๋ ๊ณผ์ -> ์์๋๋ก ํ์ํ๋๊ฒ ์๋๋ผ, ๋ฐ์์๋ถํฐ ํ์ํด์ ์ฐจ๊ทผ์ฐจ๊ทผ ์๋ก ์ฌ๋ผ๊ฐ๋ฉด์ ๋ด๋ ค์ฃผ๋๊ฒ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ด๋ค!!
๐ ์ ๋ต์ฝ๋
import Foundation
//let m = 4
//let n = 5
//let board = ["CCBDE", "AAADE", "AAABF", "CCBBF"]
// ๊ฒฐ๊ณผ๊ฐ : 14
// ๋ค๋ฅธ test case
//let m = 8
//let n = 2
//let board = ["CC", "BB", "AA", "BB", "BB", "AA", "BB", "CC"]
// ๊ฒฐ๊ณผ๊ฐ : 16
// ๋ฐ๋ก
let m = 5
let n = 6
let board = ["AAAAAA","BBAATB","BBAATB","JJJTAA","JJJTAA"]
// ๊ฒฐ๊ณผ๊ฐ : 24
func solution(_ m:Int, _ n:Int, _ board:[String]) -> Int {
// board๋ฅผ 2์ฐจ์ ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ
var newBoard = splitBoard(board)
// ์ง์ฐ๋ ์ขํ๋ฅผ ๊ธฐ๋กํ๊ธฐ ์ํ set ์ค์ & return ๊ฐ ์ค์
var removePoint = Set<[Int]>()
var cnt = 0
// ํ๋ ์ฆ 4๋ธ๋ก์ด ์์ด์ง๋๊น์ง ๋๋ ค์ผํ๋๊น, while ๋ฌธ์ผ๋ก removePoint ์กฐ๊ฑด ๊ฒ์ฌ
// ์๋ while !removePoint.isEmpty ์ ์กฐ๊ฑด์ผ๋ก ์ฃผ์๋๋ฐ, removePoint๋ ๋งค๋ฒ ์ด๊ธฐํํด์ฃผ๋๊น ์ด ์กฐ๊ฑด์ ์๋๋๊ตฌ๋๋ฅผ ๊นจ๋ณ์
while true {
// 4๋ธ๋ก ์์น ์ฐพ์์ removePoint์ ๋ฃ์ด์ฃผ๊ธฐ
for i in 0..<m-1 {
for j in 0..<n-1 {
let point = newBoard[i][j]
// ๋ง์ฝ point ๊ฐ - ๋ผ๋ฉด, ์ด๋ฏธ ์ ๊ฑฐ๋ ์์น์ด๋ฏ๋ก continue
if point == "-" {
continue
}
// ์ฌ๋ฐฉ์ ๋ณด๊ณ ๋ค point ์ ๊ฐ๋ค๋ฉด removePoint์ ํด๋น ์ขํ ์ถ๊ฐ
if newBoard[i][j+1] == point, newBoard[i+1][j] == point, newBoard[i+1][j+1] == point {
removePoint.insert([i, j])
removePoint.insert([i, j+1])
removePoint.insert([i+1, j])
removePoint.insert([i+1, j+1])
}
}
}
// removiPoint๊ฐ ์์ผ๋ฉด cnt ๋ํด์ฃผ๊ณ ๋ธ๋ก ์ง์ฐ๊ณ , ์์ผ๋ฉด ๋ cnt ์ถ๋ ฅ
if !removePoint.isEmpty {
cnt += removePoint.count
for point in removePoint {
newBoard[point[0]][point[1]] = "-"
}
removePoint = Set<[Int]>()
} else {
break
}
// ์ง๊ธ ๋ธ๋ก ์๋ ๊ณณ์ด "-"์ธ๋ฐ, ๋ธ๋ก์ ์ฐจ๋ก๋๋ก ๋ฐ์ผ๋ก ๋ด๋ ค์ค์ผํจ
// ํด๋น ์ฝ๋๋ ๋ธ๋ก์ ์ ๋๋ก ๋ฐ์ผ๋ก ๋ชป๋ด๋ ค์ฃผ๋ ๋ฌธ์ ๊ฐ ์์ด์ ์๋ ์ฝ๋๋ก ์์ !
// for i in 0..<m-1 {
// for j in 0..<n {
// let block = newBoard[i][j]
// let under = newBoard[i+1][j]
// if block != "-", under == "-" {
// newBoard[i+1][j] = block
// newBoard[i][j] = "-"
// } else {
// continue
// }
// }
// }
// ์ด๋ ๊ฒ ๋ฐ์์ ๋ถํฐ ํ์ํ๋ฉด์ ์ฌ๋ผ์ค๋ฉด์ ๋ธ๋ก์ ๋ด๋ ค์ค์ผํจ
for j in stride(from: 0, to: n, by: 1) { //์ด
var first = 0 //๋ธ๋ก์ด ๋ด๋ ค์์ผํ ํ ์์น
if newBoard[m-1][j] == "-" {
first = m-1
}
for i in stride(from: m-2, through: 0, by: -1) { //ํ
if newBoard[i][j] == "-" {
if i > first {
first = i
}
} else if newBoard[i+1][j] == "-"{
newBoard[first][j] = newBoard[i][j]
newBoard[i][j] = "-"
first -= 1
}
}
}
}
return cnt
}
func splitBoard(_ board: [String]) -> [[String]] {
var newBoard = [[String]]()
for b in board {
let arr = b.map { String($0) }
newBoard.append(arr)
}
return newBoard
}
print(solution(m, n, board))