Trouble
- 코딩테스트 문제를 푸는 중,
일정한 크기로 문자열을 나눠야하는 경우가 생겼는데 separator(공백, 특정문자 등)를 기준으로 자르는 경우는 해봤지만 원하는 크기로 일정하게 잘라본 적은 없는 것 같다.. - 2시간 가까이 머리를 싸매고 검색도 했지만 원하는 결과를 찾지는 못했다.
- 대신 문자열의 인덱스를 이용하여 일부 문자열을 얻는 방법에서 착안하여 작성해보았다.
생각한 방법
- index( , offsetBy: Int) 함수를 사용하였다.
- 문자열의 시작인덱스(newStr의 0번 인덱스)와 끝인덱스(시작인덱스로부터 offset만큼 떨어진 원소의 인덱스)를 구한다.
- newStr의 start부터 end까지를 result배열에 append 한다.
- newStr을 앞에서부터 offset만큼의 문자를 제거한다.
- 문자열의 갯수가 offset보다 작을 때까지 반복한다.
- newStr의 가장 마지막 문자열의 문자수가 offset보다 작은 경우에 나머지 문자들을 result배열에 추가하도록 if 문을 추가한다.
func cutString(_ str: String, _ offset: Int) -> [String] {
var newStr = str
var result: [String] = []
while newStr.count > offset {
let start = newStr.startIndex
let end = newStr.index(newStr.startIndex, offsetBy: offset)
// let temp = newStr[start..<end]
// result.append(String(temp))
result.append(String(newStr[start..<end]))
for _ in 0..<offset {
newStr.removeFirst()
}
if newStr.count < offset {
result.append(newStr)
}
}
return result
}
cutString("abcdefg", 2) // ["ab", "cd", "ef", "g"]
String, Character, String.Index 타입에 대해 자세히 알고 싶다면 다음 링크를 참고해주세요!
String타입은 왜 인덱스를 통해 문자에 바로 접근할 수 없을까?
To-Do🤔 : 시간복잡도를 줄이는 방법 고민해보기
- 위에 작성한 코드는 while문과 for문이 중첩되어 있으므로 시간복잡도는 O(n^2) 이다.
- 시간복잡도를 O(n)으로 만들기 위해서 생각한 방법은
- 1) offset만큼 자른 뒷부분 문자열을 인자로 넘겨주어 재귀적으로 함수를 호출하도록 구현한다.
- 2) while문 안에 index와 result 변수를 활용해 아래와 같이 해결한다.
재귀로 구현하는 것보다는 코드 라인수가 길어질 수는 있으나, 직관적으로 쉬운 아이디어로 풀 수 있었다.
아래와 같이 구현하면 while문 하나만 사용되었으므로 O(n)의 시간복잡도로 구현이 가능하다.
(코드에 대한 설명은 주석을 첨부하였습니다.)
func cutString(_ str: String, offset: Int) -> [String] {
let arr: [String] = str.map { String($0) } // 문자열을 문자 하나하나가 담긴 배열로 변형
var answer = [String]()
var index: Int = 0
var result: String = ""
if offset == str.count { // offset과 str.count가 같다면, 바로 asnwer배열에 추가
answer.append(str)
} else {
while true {
if index == arr.count { // index가 arr의 마지막 원소의 인덱스 일때
if result == "" { // result가 비어있다면 break를 통해 while문을 벗어난다.
break
} else { // result에 값이 있다면 (ex. 아래의 offset을 5를 준 경우 처럼 마지막에 5자리 이하인 "ge" 가 result에 들어 있는 경우)
answer.append(result) // result에 담긴 자투리를 answer에 추가하고 break를 통해 while문을 벗어난다.
break
}
}
// 이하는 index가 arr.count에 도달하지 않은 경우이다.
result += arr[index] // result에 arr[index] 번째를 추가
if result.count == offset { // result 문자열이 offset 길이가 되면(즉, 자르길 원하는 길이가 되면)
answer.append(result) // answer에 append 해주고
result = "" // result를 초기화 한다.
}
index += 1 // while문을 돌때마다 index값을 증가시키면서 arr의 다음원소에 대해 while문을 반복한다.
}
}
return answer
}
print(cutString("heafaf", offset: 2)) // ["he", "af", "af"]
print(cutString("hasdfsdfsdge", offset: 5)) // ["hasdf", "sdfsd", "ge"]
print(cutString("hasd", offset: 5)) // ["hasd"]
틀린부분이 있거나, 더 좋은 방법이 있다면 댓글로 남겨주세요!
🌈댓글은 언제나 환영입니다🙏🏻
반응형
'Trouble Shooting' 카테고리의 다른 글
[clipsToBounds] view안에 있는 imageView를 둥글게 하고 싶을 때 둘다 radius값을 주어야할까?? (+일부 모서리만 둥글게 하기) - iOS (4) | 2021.10.19 |
---|---|
[cornerRadius] - 동그란 버튼을 만들고 싶을 때 (2) | 2021.10.18 |
[AutoLayout] StackView에서 내가 원하는 컴포넌트를 크게 하고 싶을 때 - iOS (0) | 2021.10.13 |
collectionView - cell의 imageView를 원으로 만드는데 찌그러짐 - iOS (0) | 2021.09.30 |
tableView VS collectionView 언제 뭘 사용해야 할까? (0) | 2021.08.20 |