a = [3,10]
t = a[0]
a[0] = a[1]
a[1] = t
a
-> [10,3]
멀티 할당 이용
a[0], a[1] = a[1], a[0]
왼쪽은 new, 오른쪽은 old
제일 큰 값을 선택하고,
그 값을 제외한 나머지 들 중 제일 큰 값을 선택하고 /
... 반복(i개의 step)
arr = [20, 12, 15 10, 2]
for i_step in range(len(arr)): # 5개 원소 롤링 --> 0~4 step
# 1) 지금 i_step에서 제일 작은 친구 위치 기록
# ==> i번째 있는 친구로 초기화
min_idx = i_step
# 2) i_step +1 위치 값 부터~끝까지
for j in range(i_step+1, len(arr)):
# 비교 : 지금까지 1등 vs 새로운 값
# ==> 신규 값 : j번째
# 기존 1등 위치 : min_idx에 존재
if arr[j] < arr[min_idx]: # 신규출전자가 더 작을 때
min_idx = j
else:
pass
# i_step에서의 제일 작은값 선택 = min_idx
# 3) 기존 i_step 값과 새로운 값 자리 swap
arr[min_idx], arr[i_step] = arr[i_step], arr[min_idx]
print(arr)
"기존"에 "정렬"이 되어있는 상태에서 "중간에" 삽입
🆚 선택정렬, 크기 비교->기록 필요 없음. 계속 비교하면서 swap/stop
arr =[9, 5, 1, 4, 3]
for step in range(1, len(arr)):
for i in range(step,0,-1):
if arr[i-1] > arr[i]: #new가 더 작으면
arr[i-1], arr[i] = arr[i], arr[i-1]
else :
break #공회전 방지, 효율 증가
코드상 삽입정렬과 유사 / 개념상 선택정렬과 유사
for step in range(len(arr)):
# 앞에서 부터 2개씩 가지고 와서 비교 & 큰 것을 뒤로 swap
for i in range(0, len(arr)-step-1):
if arr[i] > arr[i+1]: # 앞의 친구가 크면 > 뒤로 보내
arr[i], arr[i+1] = arr[i+1], arr[i]
.append(), .insert().extend(), +[a,b,c] + [d,e] => [a,b,c,d,e] 단, 원본 유지되기 때문에 변수 할당 or 갱신 해줘야함. .pop(위치index), .remove(값)len().count(값), 값의 자리 index(값).reverse(), reversed().sort(key=lambda ~), sorted(list, key=lambda ~)dict[key] = value 기존 key값이 존재하면 value 갱신. del dict[key]del dict - dict 제거 , dict.clear() - 내부 원소 모두 제거 ( 틀 {} 만 남김 )dict.items() -> [ (key, value), (key, value), ... ]어렵진 않지만 자주 사용되는 구조. 익숙하게 생각하라
Q.
수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.
마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.
[제한사항]
마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.
completion의 길이는 participant의 길이보다 1 작습니다.
참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.
참가자 중에는 동명이인이 있을 수 있습니다.
[입출력 예]
pariticipant
["marina", "josipa", "nikola", "vinko", "filipa"]
completion
["josipa", "filipa", "marina", "nikola"]
return
"vinko"
A.
#포함 여부 판단 : if + in 사용. dict의 경우 key 기준.
def solution(participant, completion):
answer = ''
참가자 이름 : key, 참가자 수 : value => dict로 세팅
people_dict = {}
for p in participant:
# 기준 : 기등록이름 vs 처음등록이름
if p in people_dict: # 기등록이름
people_dict[p] +=1
else: # 신규등록
people_dict[p] =1
for c in completion:
# 기준 : 완주자가 1명 vs 2명 이상
if people_dict[c] == 1:
del people_dict[c]
else:
people_dict[c] -= 1
# 완주자 명단을 보면서 참가자 지우기 --> 1명만 남을 때까지
answer = list(people_dict.keys())[0]
return answer
#코드는 간단해도 비효율적일 수 있다.
실제 기출 1번 정도의 문제
Q.
신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.
다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.
| 유저 ID | 유저가 신고한 ID | 설명 |
|---|---|---|
| "muzi" | "frodo" | "muzi"가 "frodo"를 신고했습니다. |
| "apeach" | "frodo" | "apeach"가 "frodo"를 신고했습니다. |
| "frodo" | "neo" | "frodo"가 "neo"를 신고했습니다. |
| "muzi" | "neo" | "muzi"가 "neo"를 신고했습니다. |
| "apeach" | "muzi" | "apeach"가 "muzi"를 신고했습니다. |
각 유저별로 신고당한 횟수는 다음과 같습니다.
| 유저 ID | 신고당한 횟수 |
|---|---|
| "muzi" | 1 |
| "frodo" | 2 |
| "apeach" | 0 |
| "neo" | 2 |
위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.
| 유저 ID | 유저가 신고한 ID | 정지된 ID |
|---|---|---|
| "muzi" | ["frodo", "neo"] | ["frodo", "neo"] |
| "frodo" | ["neo"] | ["neo"] |
| "apeach" | ["muzi", "frodo"] | ["frodo"] |
| "neo" | 없음 | 없음 |
따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.
이용자의 ID가 담긴 문자열 배열 id_list, 각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.
[제한사항]
[입출력 예]
/입력
id_list = ["muzi", "frodo", "apeach", "neo"]
report = ["muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"]
k = 2
/출력
result = [2,1,1,0]
def solution(id_list, report, k):
answer = []
return answer
A.
#입력:
id_list 전체 "유저" list,
report "유저 신고유저" list, 신고 내역
k 신고 처리 기준, k번 이상 신고했을 때 처리
#출력: 신고 유저 중, 처리된 유저 개수 list. (id_list 순서대로)
#나의.. 멍청한코드..
report_dict = {}
num_report = {}
for i in report :
id, r_id = i.split(' ') #먼저 유저:신고유저 dict1에 담기
report_dict[id] = r_id
if r_id in num_report : #신고 수를 counting 해서 유저:신고수 dict2에 담고
num_report[r_id] += 1
else :
num_report[r_id] = 1
for 문 돌리면서
dict2 value>k 인 경우
for i in num_report.values() :
if i >= k :
#dict2 key값을 dict1 value에서 찾아서
#그에 상응하는 key값 -> 전체 유저 list에서 index값 찾기
#-> 순서대로 list에 갱신(+1씩)
1) 신고 하고, 2) 신고 개수에 따라 처리 여부 결정, 3) 처리된 사람을 신고한 사람을 다시 찾아서.. 4) 신고한 사람의 신고 처리된 개수를 구해야함... 왔다갔다...
💡 key : 신고 당한 사람 기준, value : 신고 한 사람들(여러명)
k값과 value의 개수를 비교하여 처리 여부 판단 ->
처리된 사람 key에서 찾고 - value(list)로 counting (id_list에서 위치 찾아서 answer에 +1 갱신)
** 한 사람을 여러 번 신고할 경우(중복) 1번으로 처리 -> value 자료형을 list ↔ set 해주면 중복 제거됨
빈 Dict 생성(k:신고 당한 사람, v:신고 한 사람들)
d = { }
id_list 통해 key값 미리 생성해두기.
d = {id:[] for id in id_list}
k값 이상 신고되어 신고 처리 된 사람
BL = []
출력 값
answer = [0] * len(id_list)
로 [0,0,0,0,..] 세팅해두고 counting해서 +1씩 갱신
2.1 report를 통해 신고 접수 결과 정리
for r in range(0,len(report)) :
value = r.split(' ')[0] : 신고한 사람 (value)
key = r.split(' ')[1] : 신고 당한 사람 (key)
if key in d :
d[key].append(value)
#pythontic한 코드 짜기
* 중복 제거 :
for i in d :
d[i] = set(d[i])
d[i] = list(d[i])
2.2 k값 이상 신고 당한 사람 filtering
if len(d[i]) >= k :
BL.append(i)
2.3 신고 처리 된 사람(BL)을 처리한 사람 counting
for i in BL :
l = d[i]
for j in l :
answer[id_list.index(j)] = +1
특이 케이스 유의
def solution(id_list, report, k):
answer = [0]*len(id_list)
reported_dict = {id:set([]) for id in id_list}
for report_pair in report: # ---> ???? set 중복신고 결과 유니크
reporter, reported = report_pair.split(" ")
reported_dict[reported].add(reporter) # *******
k_reported = [key_id for key_id, v in reported_dict.items() if len(v) >=k]
for ban_id in k_reported:
mail_res_ids = reported_dict[ban_id] # ["muzi"," apeach"]
for id in mail_res_ids:
id_index = id_list.index(id)
answer[id_index] += 1
return answer