문제
https://programmers.co.kr/learn/courses/30/lessons/60057
코딩테스트 연습 - 문자열 압축
데이터 처리 전문가가 되고 싶은 "어피치"는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문
programmers.co.kr
풀이
알고리즘 카테고리에서 어느 것에 해당하는 것인지 생각해 보았는데 (해시, 정렬, 동적계획법 등) 적절한 것이 떠오르지 않아 그냥 짜보기로 했다.
구현력을 시험하는 문제같기도 하다.
생각한 방법은 다음과 같다.
ex) aabbacccc
1. 1~문자열 길이-1 만큼 반복문을 돌며 각 자리수만큼 자른다 ex) 두개씩 자를 때 aa / bb / ac / cc / cc
2. 딕셔너리에 저장하여 중복을 체크한다. ex ) aa: 1, bb: 1, ac: 1, cc:2
3. 각 자리수로 자른 것들의 최종 문자 개수를 센다
4. 가장 작은 값을 반환한다.
from collections import Counter
def solution(s):
answer = 0
results = [0 for i in range(len(s) - 1)]
for i in range(1, len(s)):
dic = {}
for j in range(0, len(s), i):
if j + i > len(s):
break
if s[j:j+i] in dic:
dic[s[j:j+i]] += 1
else:
dic[s[j:j+i]] = 1
for v in dic.values():
if v == 1:
results[i-1] += i
else:
results[i-1] += i+1
print(dic)
print(results)
return answer
라고 생각하고 짰는데.. 생각해보니 앞-뒤에 연결된 것만 중복으로 치고 aabcaa 에서 앞 aa와 뒤 aa는 압축이 안 된다는 것을 고려 안했다.
순서를 반영하지 않는 딕셔너리에서 자른 문자열과 압축 횟수를 저장하는 튜플의 리스트로 변경해서 다시 짰다.
근데 튜플은 값 변경이 되지 않는다 해서 다시 이중배열로 짬..
from collections import Counter
def solution(s):
results = [0 for i in range(len(s) - 1)]
for i in range(1, len(s)):
arr = []
k = 0
for j in range(0, len(s), i):
if j + i > len(s):
results[i-1] += len(s)-j
break
if j == 0 or arr[k-1][0] != s[j:j+i]:
arr.append([s[j:j+i], 1])
k += 1
else:
arr[k-1][1] += 1
for a in arr:
if a[1] == 1:
results[i-1] += i
else:
results[i-1] += (i+1)
return min(results)
예외가 있나보다 ㅜ
"aaaaaaaaaa"처럼 중복이 10번 이상 되는 문자열의 경우에서 내가 자릿수를 1로 처리해버려서 발생하는 오류였다.
마지막 반복문에서
else:
results[i-1] += i + len(str(a[1]))
로 바꿔주면서 오류는 해결됐다.
테스트케이스 5번 런타임 에러는 문자열의 길이가 1일때 발생하는 배열 인덱스 오류였던 같다.
최종 코드
def solution(s):
results = [0 for i in range(len(s)//2)]
if len(s) == 1:
return 1
for i in range(1, len(s)//2 + 1):
arr = []
k = 0
for j in range(0, len(s), i):
if j + i > len(s):
results[i-1] += len(s)-j
break
if j == 0 or arr[k-1][0] != s[j:j+i]:
arr.append([s[j:j+i], 1])
k += 1
else:
arr[k-1][1] += 1
for a in arr:
if a[1] == 1:
results[i-1] += i
else:
results[i-1] += i + len(str(a[1]))
return min(results)
다른 사람의 풀이
def compress(text, tok_len):
words = [text[i:i+tok_len] for i in range(0, len(text), tok_len)]
res = []
cur_word = words[0]
cur_cnt = 1
for a, b in zip(words, words[1:] + ['']):
if a == b:
cur_cnt += 1
else:
res.append([cur_word, cur_cnt])
cur_word = b
cur_cnt = 1
return sum(len(word) + (len(str(cnt)) if cnt > 1 else 0) for word, cnt in res)
def solution(text):
return min(compress(text, tok_len) for tok_len in list(range(1, int(len(text)/2) + 1)) + [len(text)])
로직 자체는 크게 다를 것 없어 보이는데 코드가 많이 다르다
파이썬은 언제쯤 익숙해질까 흑흑
'알고리즘 스터디 2021.07~' 카테고리의 다른 글
[프로그래머스] 2018 카카오 블라인드 - [1차] 추석 트래픽 (0) | 2021.07.16 |
---|---|
[프로그래머스] 2019 카카오 겨울인턴 - 크레인 인형뽑기 (2) | 2021.07.16 |
[프로그래머스] 2019 카카오 오픈채팅방 (1) | 2021.07.08 |
[프로그래머스] 2021 카카오 메뉴 리뉴얼 (1) | 2021.07.04 |
[프로그래머스] 2021 카카오 신규 아이디 (0) | 2021.07.04 |