-
Programmers) Lv2 [2020카카오공채] 문자열 압축Algorithm/Programmers 2020. 3. 16. 15:24728x90
출처: https://programmers.co.kr/learn/courses/30/lessons/60057
분류: Lv2 문자열
접근방식
문자열의 길이 N의 절반 이상으로 자르면 압축할 수가 없습니다.
주의 할 개념은 이정도 나머지는 구현이 핵심입니다.문자열을 다룰 수 있고, 아래 예시와 같이 문자열과 관련된 다양한 작업을 할 수 있는지 파악
- 문자열 자르기
- 부분 문자열 얻기
- 문자열 비교하기
- 문자열 길이 얻기
Swift 는 문자열 다루기가 상대적으로 까다로운데 자유자재로 사용하려면 역시 많은 연습이 필요하겠습니다 😥
해결방법
1 ~ N/2 까지 잘라가며 압축 문자열의 길이가 가장 작은 값을 찾아냅니다.
앞에서부터 압축 문자열의 길이로 잘라내면서 중복을 카운트합니다.
카운트가 1이면 중복을 카운트 없이 부분 문자열을 result 에 추가시키고
1 보다 크면 카운트를 앞에 붙여줍니다.일일이 분기처리를 하기 싫어서 처음에 카운트가 "1" 이여도 일단 다 붙이고
이후에 1을 제거하는 방식도 생각했었는데
이렇게 하면 1000 과 같이 10 이상의 수의 1도 잘라버릴 수가 있습니다 😇func solution(_ s:String) -> Int { var resultCount = s.count if s.count == 1 { return 1 } for idx in 1...s.count/2 { var result = "" var indiceStr = "" var cnt = 1 var str = s while str.count >= idx { let range = str.startIndex..<str.index(str.startIndex, offsetBy: idx) if indiceStr == str[range] { cnt += 1 } else { if cnt == 1 { result += "\(indiceStr)" } else { result += "\(cnt)\(indiceStr)" } indiceStr = String(str[range]) cnt = 1 } str.removeFirst(idx) } if cnt == 1 { result += "\(indiceStr)\(str)" } else { result += "\(cnt)\(indiceStr)\(str)" } if resultCount > result.count { resultCount = result.count } } return resultCount }
개선된 코드
swift에는 기본적으로 문자열을 특정 길이로 자르는 함수는 제공하지 않습니다.
이 부분을 구현하는 부분 때문에 코드가 복잡해질 수 있는데,
문자열을 자르는 부분을 extension으로 처리해주면 보다 깔끔하게 처리할 수 있습니다.extension String { func split(by length: Int) -> [String] { var resultString = [String]() var string = self while string.count >= length { let range = string.startIndex..<string.index(string.startIndex, offsetBy: length) resultString.append(String(string[range])) string.removeFirst(length) } if !string.isEmpty { resultString.append(string) } return resultString } } func solution(_ s:String) -> Int { if s.count == 1 { return 1 } var resultCount = s.count for idx in 1...s.count/2 { let truncatedString = s.split(by: idx) var duplicatedStr = "" var dupCnt = 1 var result = "" for str in truncatedString { if str == duplicatedStr { dupCnt += 1 } else { if dupCnt == 1 { result += duplicatedStr } else { result += "\(dupCnt)\(duplicatedStr)" } duplicatedStr = str dupCnt = 1 } //print(str, duplicatedStr, dupCnt, result) } if dupCnt > 1 { result += "\(dupCnt)\(duplicatedStr)" } else { result += "\(duplicatedStr)" } //print(truncatedString, idx, result) if resultCount > result.count { resultCount = result.count} } return resultCount
여전히 1을 분기처리 하는 부분이 두 번이나 사용되서
깔끔해 보이지 않아 맘에들지 않네요.. 더 좋은 방법이 있을까요 ㅠ-ㅠ배운점
간단한 문제인데 꽤나 오랜 시간이 걸렸다.
문자열은 거의 빼놓지 않고 한 문제씩은 꼭 나오는 데 확실히 연습해서 시간을 단축하자.역시 코드는 네이밍이 정말 중요하다..
문자열을 다룰 때는 subString이 많이 사용되기 때문에 str, s, 이런 식으로 사용하면
내 코드에 내가 빠져 허우적 허우적....
너무 줄이지 말고 깔끔하고 명확한 네이밍을 하자.
이름을 줄이지 말고 코드를 줄이자 😭😭extension을 적극적으로 활용하면 더 가독성 높고 깔끔한 코드를 완성시킬 수가 있다.
'Algorithm > Programmers' 카테고리의 다른 글
Programmers) Lv3 [2020카카오공채] 자물쇠와 열쇠 (0) 2020.04.03 Programmers) Lv2 [2020카카오공채] 괄호 변환 (0) 2020.03.25 Programmers) Lv2 스킬트리 (0) 2020.03.15 Programmers) Lv3 섬 연결하기 (0) 2020.03.06 Programmers) Lv2 조이스틱 (0) 2020.01.29