[문자열] PRG 17677: [1차] 뉴스 클러스터링

KimRiun·2021년 12월 5일
0

알고리즘_문제

목록 보기
25/26

사용 언어: python 3.9.5

❓ Problem

문제 설명

https://programmers.co.kr/learn/courses/30/lessons/17677

난이도

level2

🚩 Solution

시도 01)

1. 접근법

  1. 전처리

    모두 소문자로 바꾸기

    특수문자, 공백, 숫자는 '0'으로 바꾸기

  2. 두 리스트가 모두 공집합일 때, 어느 한 리스트라도 공집합일 때 처리하기

    모두 공집합 : 65536 반환

    하나라도 공집합 : 0 반환(교집합이 항상 0이므로)

  3. 중복이 허용된 교집합 원소 수 구하기

    1. 일단 중복없는 교집합 구하기

      ex) [1,2,3,3,3,4,5] 와 [3,3,4,5,5,6,7] 라면 [3,4,5]를 구함

    2. 구한 교집합 원소를 하나씩 각각의 리스트에서 몇 개 있는지 구해서 더 적은 개수 더해가기

      ex) 교집합 [3,4,5]에서 3이 각각 몇개씩 있는지 구하고, 더 적은 개수를 택한다.

      첫번째 리스트에는 3이 3개 있고 두번째 리스트에서는 3이 2개 있으므로 교집합 개수는 2다.

      다음으로 4는 첫번째 리스트에 1개, 두번째 리스트에 1개 있으므로 현재까지 교집합 개수는 2+1= 3이다.

      5는 첫번째 리스트에 1개, 두번째 리스트에 2개 있으므로 교집합 개수는 3+1=4가 된다.

  4. 중복이 허용된 합집합 원소 수 구하기(중복 허용)

    두 리스트의 원소의 합을 구한 뒤 교집합 수를 빼면 합집합 원소의 개수가 된다.

2. 코드

import re

def change(str):
    return re.sub('[^a-z]', '0', str.lower())

def set2(str):
    list1 = []
    for i in range(len(str)-1):
        if '0' not in str[i:i+2]:
            list1.append(str[i:i+2])
    return list1

def solution(str1, str2):

    # 전처리 : 모두 소문자로, 특수/숫자/공백은 숫자 0으로
    str1 = change(str1)
    str2 = change(str2)

    # 0을 포함하지 않도록 2개씩 원소 묶기
    list1 = set2(str1)
    list2 = set2(str2)

    if (not list1) and (not list2):
        return 65536
    if (not list1) or (not list2):
        return 0

    # 교집합
    inter_cnt = 0
    inter = set(list1).intersection(set(list2))
    for i in inter:
        inter_cnt += min(list1.count(i), list2.count(i))

    # 합집합
    union_cnt = len(list1) + len(list2) - inter_cnt

    return int(inter_cnt/union_cnt * 65536)

3. 결과

성공

4. 소요 시간

60분

📕 피드백

1. 검색한 내용

소문자만 있는 문자열로 만들기 :

import re
# re.sub('소문자를 제외한 문자들', '0으로 바꾼다', 타겟 문자열 )
re.sub('[^a-z]', '0', str.lower())

교집합 구하기 : set3 = set1.intersection{set2)

합집합 구하기 : set3 = set1.union(set2)

profile
Java, Python

0개의 댓글