본문 바로가기

운동하는 개발자/알고리즘, 코딩테스트

HackerRank [Strings] Sherlock and the Valid String /알고리즘 해커랭크

728x90

문제 주소 : https://www.hackerrank.com/challenges/sherlock-and-valid-string/problem

난이도 : Medium
성공률 : 64.75%

 

문제 : 셜록 규칙에 맞는 유효한 문자열 찾기
1. 모든 문자가 동일한 개수여야 유효하다
2. 오직의 하나의 문자를 제거할 수 있다

 

풀이 : 코드 주석 참고

 

답안

import math
import os
import random
import re
import sys
import collections


def isValid(s):
    dic :dict = collections.Counter(s)    #딕셔너리를 통하여 각 문자와 개수 산출 (a는2개 b는3개)
    dic2 : dict = collections.Counter(dic.values())  #각 문자 개수에 대해서 카운트 (2개있는 문자 2개 3개있는 문자 1개)

    if len(dic2) > 2:   #문자의 개수 종류가 3개 이상이면 하나의 문자를 삭제하더라도 동일한 개수가 될 수 없다
        return 'NO'
    elif len(dic2) == 1: #문자 개수 종류가 한가지만 이미 모두 동일한 문자 개수이다
        return 'YES'
                
    total : list = dic2.most_common()   #2개를 리스트로 획득 많은 문자 개수 순으로 나옴(aabcd 라면 [3:3][2:1]

    if abs(total[0][0] - total[1][0]) == 1: #문자의 개수가 2종류라도 그 개수가 차이가 하나일 때 (aabbccc 일 때 2개문자 2개 3개문자 1개) #반대로 aaabcd 1개문자 3개 3개문자 1개라면 지워도 소용없으므로
        if total[1][1] ==1:                 #차이가 하나이며 적은 문자개수가 1인경우 (ababc 일 때 c가 1개)
            return 'YES'
    elif total[1][0] == 1:                  #적은 문자 개수가 하나인 경우 (aaabbbc 일 때 c가 한개)
        return 'YES'    

    return 'NO' 


if __name__ == '__main__':
    # fptr = open(os.environ['OUTPUT_PATH'], 'w')
    fptr = sys.stdout

    s = input()

    result = isValid(s)

    fptr.write(result + '\n')

    fptr.close()

 

느낀점

더보기
역시 배워야한다... 딕셔너리도 있다는거만 알고 첨써보고 이렇게 편하게 카운트를 세어주고 리스트로 변환하고 
import collections 요기 있는 함수들은 각 코딩테스트에서도 사용가능하다고 한다
"마지막에 많은 문자 개수와 적은문자 개수의 차이가 크지만 적은 문자 개수가 하나인 경우"(elif total[1][0] ==1) 케이스를 생각못해서 2개의 케이스를 통과못하다가 예제 열어보기로 풀었다 
단순히 적은문자 개수가 하나인경우 위의 케이스에서 빠져나가버려서 생각못했음
처음으로 통과율 80퍼 미만의 문제를 풀었다 뿌듯..

 

728x90