문제 설명 문자열 s가 입력되었을 때 다음 규칙을 따라서 이 문자열을 여러 문자열로 분해하려고 합니다.먼저 첫 글자를 읽습니다. 이 글자를 x라고 합시다. 이제 이 문자열을 왼쪽에서 오른쪽으로 읽어나가면서, x와 x가 아닌 다른 글자들이 나온 횟수를 각각 셉니다. 처음으로 두 횟수가 같아지는 순간 멈추고, 지금까지 읽은 문자열을 분리합니다. s에서 분리한 문자열을 빼고 남은 부분에 대해서 이 과정을 반복합니다. 남은 부분이 없다면 종료합니다. 만약 두 횟수가 다른 상태에서 더 이상 읽을 글자가 없다면, 역시 지금까지 읽은 문자열을 분리하고, 종료합니다.문자열 s가 매개변수로 주어질 때, 위 과정과 같이 문자열들로 분해하고, 분해한 문자열의 개수를 return 하는 함수 solution을 완성하세요.
제한사항 1 ≤ s의 길이 ≤ 10,000s는 영어 소문자로만 이루어져 있습니다.
입출력 예 입출력 예 설명 입출력 예 #1 s="banana"인 경우 ba - na - na와 같이 분해됩니다. 입출력 예 #2 s="abracadabra"인 경우 ab - ra - ca - da - br - a와 같이 분해됩니다. 입출력 예 #3 s="aaabbaccccabba"인 경우 aaabbacc - ccab - ba와 같이 분해됩니다.
🔵 풀이 - removeFirst(), inout &
처음에 문제를 이해하는 게 어려웠는데, 아래처럼 직접 표를 그려보니 이해가 되었다.
문자열을 읽어나가면서 x와 같은 문자 수와 x와 다른 문자 수가 같아지면 문자열을 자르고
문자열이 잘릴 때마다 x가 새롭게 바뀌는 것이었다.
s
a
a
a
b
b
a
c
c
c
c
a
b
b
a
x
a
c
b
== x
1
1
1
1
1
1
1
!= x
1
1
1
1
1
1
1
나는 해당 로직을 수행하는 execute 함수를 따로 만들었고, 전체 코드는 아래와 같다.
import Foundation
func solution(_ s:String) -> Int {
var leftString: [Character] = Array(s)
var numOfSlice: Int = 0
while leftString != [] {
numOfSlice += 1
execute(&leftString)
}
return numOfSlice
}
func execute(_ leftString: inout [Character]) {
let x = leftString.removeFirst()
var same: Int = 1
var diff: Int = 0
while leftString != [] {
let target = leftString.removeFirst()
if x == target {
same += 1
} else {
diff += 1
}
if same == diff{
break
}
}
}
🥕 함수 파라미터 변경하기 ; 'inout', '&' 키워드
여기서, 함수의 파라미터로 받은 값을 inout, & 키워드를 통해 수정할 수 있다 (참고: 카공남의 작업스토리)
파라미터로 받은 값을 수정한다는 게 무슨 의미냐면....
일반적으로 함수는 다음과 같이 정의하며, 파라미터는 상수(let)로 선언되어 변경할 수 없다.
// 일반적인 함수 정의
func 함수명(argumentLabel parameterName: dataType) {
statements
}
그러나 파라미터 값을 함수 내부에서 수정하고 싶다면,
함수 선언부에서 자료형 앞에 'inout' 이라는 키워드를 붙이고,
함수를 호출할 때 파라미터 앞에 '&' 키워드를 붙이면 된다.
// 함수 선언 - 자료형 앞에 'inout' 붙이기
func execute(_ leftString: inout [Character]) {
statement
}
// 함수 호출 - 파라미터 앞에 '&' 붙이기
execute(&["a", "c", "d"])
🥕 개선점
- leftString != [] 대신 !leftString.isEmpty 를 사용하는 게 더 좋다고 한다!
- 풀이 2처럼 변수를 1개로 통일하고 삼항연산자를 사용하면 코드가 더 짧아질 것이다!
🔵 풀이 2 - 로직 변경 (변수 줄이기, 삼항연산자 사용하기)
나는 x와 같은 문자 수, 다른 문자 수를 각각의 변수로 두고, 그 둘이 같아지는 순간에 문자열을 잘랐는데,
다른 사람의 풀이를 보다가 하나의 변수에 + 1 또는 - 1하여 값이 0이 되는 순간에 문자열을 자르는 풀이를 발견했다.
또한, 이 분은 if else문을 삼항연산자로 줄여서 코드가 더 짧아졌다.
import Foundation
func solution(_ s:String) -> Int {
var answer = 0
var x: Character? = nil
var xCount = 0
for i in s {
if x == nil {
x = i
xCount = 1
answer += 1
continue
}
xCount += x == i ? 1 : -1
if xCount == 0 {
x = nil
}
}
return answer
}