문제 링크 / Github 링크 |
---|
import Foundation
func solution(_ t: String, _ p: String) -> Int {
return 0
}
import Foundation
func solution(_ t: String, _ p: String) -> Int {
var mutableT = t
var resultCount = 0
let intP = Int(p)!
while mutableT.count != p.count {
var numString = ""
for char in mutableT {
numString.append(char)
if numString.count == p.count { break }
}
if Int(numString)! <= intP { resultCount += 1 }
mutableT.removeFirst()
}
if Int(mutableT)! <= intP { resultCount += 1 }
return resultCount
}
mutableT
에서 매번 첫 글자를 제거하며 p.count
길이의 부분 문자열을 만들어 확인하는 로직은 비효율적이다.mutableT.removeFirst()
로 문자열을 매번 수정하는 부분은 O(n) 연산이다. 전체적인 시간 복잡도가 높아질 수 있다.if
문에서 mutableT
의 길이가 p.count
와 같은지 확인 후 비교하는 코드는 앞의 로직과 유사하여 중복 코드로 간주될 수 있다.import Foundation
func solution(_ t: String, _ p: String) -> Int {
let intP = Int(p)!
let pCount = p.count
var resultCount = 0
for i in 0...(t.count - pCount) {
let startIndex = t.index(t.startIndex, offsetBy: i)
let endIndex = t.index(startIndex, offsetBy: pCount)
let substring = String(t[startIndex..<endIndex])
if let intSubstring = Int(substring), intSubstring <= intP {
resultCount += 1
}
}
return resultCount
}
슬라이딩 윈도우 기법은 연속적인 데이터에서 특정 구간(윈도우)을 효율적으로 처리하기 위한 알고리즘 기법이다.
주로 배열이나 문자열과 같은 선형 데이터 구조에서 연속된 부분 구간의 합이나 최대/최소값, 특정 조건을 만족하는 부분 구간의 개수 등을 계산할 때 사용된다.
예시: 배열에서 크기가 k
인 부분 배열의 합을 모두 구하는 문제
func sumOfSubarrays(arr: [Int], k: Int) -> [Int] {
var sums = [Int]()
for i in 0...(arr.count - k) {
let sum = arr[i..<i+k].reduce(0, +)
sums.append(sum)
}
return sums
}
func sumOfSubarrays(arr: [Int], k: Int) -> [Int] {
var sums = [Int]()
var windowSum = arr[0..<k].reduce(0, +) // 첫 윈도우의 합 계산
sums.append(windowSum)
for i in 1...(arr.count - k) {
windowSum = windowSum - arr[i - 1] + arr[i + k - 1] // 이전 윈도우 결과 재활용
sums.append(windowSum)
}
return sums
}
문자열에서 길이 k
인 부분 문자열 중 특정 조건(예: 사전 순서 최소/최대, 특정 문자 포함)을 만족하는 개수를 구하는 문제
func smallestSubstring(s: String, k: Int) -> String {
var smallest = s.prefix(k)
for i in 1...(s.count - k) {
let startIndex = s.index(s.startIndex, offsetBy: i)
let endIndex = s.index(startIndex, offsetBy: k)
let substring = s[startIndex..<endIndex]
if substring < smallest {
smallest = substring
}
}
return String(smallest)
}
startIndex
let text = "Hello, Swift!"
print(text[text.startIndex]) // "H"
endIndex
let text = "Hello, Swift!"
let lastIndex = text.index(before: text.endIndex)
print(text[lastIndex]) // "!"
index(after:)
let text = "Hello"
let secondIndex = text.index(after: text.startIndex)
print(text[secondIndex]) // "e"
index(before:)
let text = "Hello"
let lastIndex = text.index(before: text.endIndex)
print(text[lastIndex]) // "o"
index(_:offsetBy:)
offset
만큼 떨어진 인덱스를 반환한다.let text = "Hello, Swift!"
let index = text.index(text.startIndex, offsetBy: 7)
print(text[index]) // "S"
index(_:offsetBy:limitedBy:)
offset
만큼 떨어진 인덱스를 반환하되, limit
을 넘지 않으면 해당 인덱스를 반환한다. 만약 limit
을 넘으면 nil
을 반환한다.let text = "Hello"
if let safeIndex = text.index(text.startIndex, offsetBy: 10, limitedBy: text.endIndex) {
print(text[safeIndex])
} else {
print("Index out of bounds") // 출력
}
distance(from:to:)
let text = "Hello, Swift!"
let start = text.startIndex
let end = text.index(before: text.endIndex)
let distance = text.distance(from: start, to: end)
print(distance) // 12
firstIndex(of:)
let text = "Hello, Swift!"
if let index = text.firstIndex(of: "S") {
print(index) // 0번째 인덱스
print(text[index]) // "H"
}
lastIndex(of:)
let text = "Hello, Swift!"
if let index = text.lastIndex(of: "l") {
print(index) // 3번째 인덱스
print(text[index]) // "l"
}
firstIndex(where:)
let text = "Hello, Swift!"
if let index = text.firstIndex(where: { $0.isUppercase }) {
print(index) // 0번째 인덱스
print(text[index]) // "H"
}
lastIndex(where:)
let text = "Hello, Swift!"
if let index = text.lastIndex(where: { $0.isLowercase }) {
print(index) // 12번째 인덱스
print(text[index]) // "t"
}
indices
startIndex
부터 endIndex
이전까지의 범위를 제공한다.let text = "Swift"
for index in text.indices {
print(text[index], terminator: " ") // "S w i f t"
}
와 인덱스 정리 말끔.. 조아요