백준 1152: 단어의 개수

KimRiun·2021년 4월 21일
0

알고리즘_문제

목록 보기
4/26

사용 언어: python 3.7.4

❓ Problem

문제 설명

문제

영어 대소문자와 띄어쓰기만으로 이루어진 문자열이 주어진다. 이 문자열에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오. 단, 한 단어가 여러 번 등장하면 등장한 횟수만큼 모두 세어야 한다.

입력

첫 줄에 영어 대소문자와 띄어쓰기로 이루어진 문자열이 주어진다. 이 문자열의 길이는 1,000,000을 넘지 않는다. 단어는 띄어쓰기 한 개로 구분되며, 공백이 연속해서 나오는 경우는 없다. 또한 문자열의 앞과 뒤에는 공백이 있을 수도 있다.

출력

첫째 줄에 단어의 개수를 출력한다.

백준 1152번: 단어의 개수

🚩 Solution

1. 접근법

TRY1

입력받은 문자열을 공백으로 쪼개서 리스트로 만들면, 리스트의 원소의 개수가 원하는 답이라고 생각했다.
하지만 문제에서 문자열 앞 뒤로 공백이 있을 수도 있다는 조건을 놓쳐서 틀렸다.

string = input()
print(len(string.split(' ')))

TRY2

문자열 앞 혹은 뒤에 공백이 있을 경우, 리스트 원소로 ''(빈 문자)가생기므로 ''를 제거하는 코드가 필요했다.
for문과 리스트의 remove 메소드를 사용하면 잘 제거될 거라고 생각했다.
하지만 remove한 원소의 바로 다음 index의 원소는 확인되지 않고 넘어간다는 사실을 몰랐어서, 공백이 들어오면 틀린다는 것을 알게 되었다.

string = input()
str_list = string.split(' ')
for item in str_list:
    if item == '':
        str_list.remove('')
    
#print(str_list)
print(len(str_list))

▽추가설명▽
"a a b c"라는 문자열에서 'a'를 모두 지우고 싶다고 하자.
코드처럼 remove('a')를 하면 첫번째 'a'는 제거된다.
하지만, 첫번째 'a'를 제거하면 리스트의 index가 재배치되어 두번째 'a'의 인덱스가 0이 된다. 그러면 다음으로 검사할 인덱스가 1인 원소는 b가 되고, 두번째 'a'는 검사하지 않고 넘어가기 때문에 제거하지 못한다. 결국 리스트를 출력해보면 첫번째 'a'만 제거해서 ['a', 'b', 'c']가 나온다.

 마찬가지로 공백인 문자열이 들어왔을 때, 공백으로 쪼갠 리스트는 ['', ''] 이다. remove('')를 하면 첫번째 ''는 제거하지만 두번째 ''는 제거하지 않기 때문에 최종적으로 리스트의 길이가 0이 아니고 1이므로 틀리는 것이다.

TRY3

 while문을 통해 해결했다.
또 다른 방법으로, 특정 문자열과 같지 않은 모든 문자로 다시 리스트를 만드는 방법도 있었다.

 두 방법 모두 정답이고, 백준에서 채점했을 때 걸린 시간은 똑같았다. 하지만, 메모리 사용량으로 비교해봤을 때, while문 방법은 36368 KB, 리스트 생성 방법은 37736 KB 였다.
따라서 while문 방법이 메모리를 더 적게 차지해서 좋다고 판단했다.

2. 코드

1) 특정 문자열을 직접 제거한다

while문과 리스트의 remove 메소드 사용

string = input()
str_list = string.split(' ')

while '' in str_list:
    str_list.remove('')

print(len(str_list))

2) 특정 문자열을 포함하지 않는 리스트를 만든다

string = input()
str_list = string.split(' ')

str_list = [i for i in str_list if i != '']

print(len(str_list))

3. 결과

채점 결과

correct

메모리시간코드길이
36368 KB92 ms115 B

시간 복잡도 분석

O(N)

📕 피드백

1. 검색한 내용

  1. 특정 문자로 문자열을 쪼개는 방법: string.split('특정 문자')

  2. 특정 문자를 문자열에서 제거하는 방법:

    (1) string.remove('특정 문자')

    ※ remove 메소드는 문자열에서 처음 등장하는 특정 문자만 제거하므로, 특정 문자를 모두 지우고 싶으면 반복문(while 추천)을 사용해야 한다.

    (2) 특정 문자를 포함하지 않는 리스트를 다시 만드는 것도 특정 문자를 제거한 것과 같은 효과를 볼 수 있다.

2. 실수

  1. 문제의 조건을 한 개 놓쳤다.
  2. 중간 출력문을 지우지 않고 제출해서 '출력 초과' 메세지를 받았다.

3. 발전 방향

  1. 문제 조건을 놓치지 않기 위해 문제를 이해한 후, 다시 한 번 더 읽도록 한다.
  2. 코드를 제출하기 전, 출력 결과를 예시 출력과 비교하고 제출하도록 한다.
  3. 반대로 생각하기도 해보자. 특정 문자를 포함하지 않기 위해 '특정 문자 제거하기' 대신에 '특정 문자가 없이 다시 만들기'도 있다. 어쩌면 더 쉽게 푸는 방향이 될 수도 있다.

4. 느낀점

for문과 remove 메소드를 사용했을 때 특정문자가 완전히 제거되지 않는 것을 보고 처음에는 출력 프로그램을 의심했다. 하지만 역시 코드가 문제인 거니까 괜히 출력 프로그램을 의심하는 1초의 시간도 낭비하지 말자.

profile
Java, Python

0개의 댓글