뚝딱햄 탈출기

[Python][백준 BOJ Silver V] 1181. 단어 정렬 : 리스트 중복 제거, sort(), 다중 조건 정렬, lambda, 문자열 비교 본문

Algorithm & Data structure/알고리즘 문제 풀이

[Python][백준 BOJ Silver V] 1181. 단어 정렬 : 리스트 중복 제거, sort(), 다중 조건 정렬, lambda, 문자열 비교

hyrmzz1 2023. 10. 16. 17:47

내 풀이

import sys
n = int(sys.stdin.readline())
tc =[sys.stdin.readline().strip() for i in range(n)]

# 중복 단어 제거
tc = list(set(tc))  # sort()는 리스트 메서드이므로 다시 리스트형으로 변환.

# 길이 짧은 순으로 정렬 후 길이 같으면 사전 순으로 정렬
tc.sort(key = lambda x : (len(x), x))

# 단어 한 줄에 하나씩 출력
for i in tc:
    print(i)

풀이 방식

처음엔 문제에 기술된 순서대로 코드를 작성하려 했다.
 

  1. 단어 길이 순으로 정렬
  2. 단어의 길이가 같고, 두 단어가 같으면 단어 한개 삭제 (중복 제거)
  3. 단어의 길이가 같고, 두 단어가 다르면 사전 순으로 정렬

그러나 길이 순으로 정렬한 후 2와 3을 조건문을 통해 구현하면 복잡해져서
먼저 중복되는 단어를 제거한 후에 정렬하는 방식으로 코드를 작성했다.

리스트에서 중복된 값 제거하기 ⭐ 

  1. set(집합) 자료형 이용
  2. for 반복문 이용

1. set을 이용한 리스트 중복 제거

set 자료형은 중복을 허용하지 않으며 순서가 없다.
리스트나 튜플은 순서가 있어 인덱싱을 통해 자료형의 값을 얻을 수 있는 반면에, 사전과 집합은 순서가 없어 인덱싱으로 값을 얻을 수 없다. 사전과 다르게 집합은 키(Key)가 존재하지 않고 값(Value) 데이터만을 담는다.
 
set() 함수를 이용해 리스트를 set 자료형으로 변환하면 중복되는 값들이 제거된다.

arr = [6, 5, 6, 4, 4, 1, 1, 2, 3, 9, 8, 7, 9, 8, 7]
result = set(arr)
print(result)	# {1, 2, 3, 4, 5, 6, 7, 8, 9}

이 문제에선 정렬을 위해 리스트형 메서드인 sort() 를 사용하기 때문에 set로 변환 후에 다시 리스트로 변환했다.

2. for 반복문 이용

중복되지 않는 요소들만을 저장할 새로운 리스트(result)를 생성한 후에
리스트의 모든 요소를 순회하며 해당 요소가 리스트(result) 내에 있는지 확인하고, 없으면 해당 요소를 리스트(result)에 넣는다.

arr = [6, 5, 6, 4, 4, 1, 1, 2, 3, 9, 8, 7, 9, 8, 7]
result = [] # 중복 제거된 값들이 들어갈 리스트

for value in arr:
    if value not in result:
        result.append(value)

print(result)	# {1, 2, 3, 4, 5, 6, 7, 8, 9}

리스트에서 중복된 값을 제거한 후에 sort() 함수를 이용해 정렬을 진행했다.
이 문제는 정렬 조건이 두 개인데, lambda 표현식을 사용하면 다중 조건 정렬을 간단하게 구현할 수 있다 !

Lambda 표현식을 이용한 다중 조건 정렬 ⭐

참고) sorted() 메서드는 내장 함수, sort() 메서드는 리스트형 메서드.

1. 한가지 조건에 대해 정렬

문자열의 길이 순으로 정렬

list = ['my', 'name', 'is', 'bbbb', 'aaaa']
print(sorted(list, key = lambda x : len(x)))	# ['my', 'is', 'name', 'bbbb', 'aaaa']
print(sorted(list, key = lambda x : -len(x)))	# ['name', 'bbbb', 'aaaa', 'my', 'is']
list = ['my', 'name', 'is', 'bbbb', 'aaaa']
list.sort(key = lambda x : len(x))
print(list)	# ['my', 'is', 'name', 'bbbb', 'aaaa']

오름차순 정렬이 default이고, '-'를 붙이면 내림차순으로 정렬된다.

 
사전 순 정렬

list = ['my', 'name', 'is', 'bbbb', 'aaaa']
print(sorted(list, key = lambda x : x))	# ['aaaa', 'bbbb', 'is', 'my', 'name']
print(sorted(list, key = lambda x : x, reverse = True))	# 역순 정렬. -x 쓰면 안된다...!
list = ['my', 'name', 'is', 'bbbb', 'aaaa']
list.sort(key = lambda x : x)
print(list)	# ['aaaa', 'bbbb', 'is', 'my', 'name']

2. 여러 조건에 대해 정렬

비교할 아이템의 요소가 복수 개일 경우, 튜플로 그 순서를 내보내주면 된다. 앞에 오는 것이 우선 조건!
길이 순으로 정렬 후에, 같은 길이인 요소들은 사전 순으로 정렬하려면 아래와 같이 작성한다.

list = ['my', 'name', 'is', 'bbbb', 'aaaa']
list.sort(key = lambda x : (len(x), x))
print(list)	# ['is', 'my', 'aaaa', 'bbbb', 'name']

사전순으로 정렬하는 방법에 대해 알아보다가, 문자열에 비교 연산자 <, > 를 사용하면 사전식 순서를 확인할 수 있다는 걸 알게되었다.

print('a' < 'b')	# True
print('a' > 'b')	# False

리스트의 요소를 한 줄에 하나씩 출력할 때

나는 for 문을 이용했는데, join()을 사용해 출력하는 방식의 풀이를 보았고 기억해두면 좋을듯하여 정리한다!

join()

join()은 매개변수로 들어온 리스트에 있는 요소 하나하나를 합쳐서 하나의 문자열로 바꾸어 반환하는 함수이다.
 
'구분자'.join(리스트)를 이용하면 리스트의 값과 값 사이에 '구분자'에 들어온 구분자를 넣어서 하나의 문자열로 합쳐준다.
구분자에 아무 것도 넣지 않고 ''.join(list) 로 작성하면 list = ['a', 'b', 'c']를 'abc'의 문자열로 합쳐서 반환해준다. 

print("\n".join(tc))	# tc의 모든 요소 개행하여 출력.

 


https://www.acmicpc.net/problem/1181

 

1181번: 단어 정렬

첫째 줄에 단어의 개수 N이 주어진다. (1 ≤ N ≤ 20,000) 둘째 줄부터 N개의 줄에 걸쳐 알파벳 소문자로 이루어진 단어가 한 줄에 하나씩 주어진다. 주어지는 문자열의 길이는 50을 넘지 않는다.

www.acmicpc.net

Comments