[Programmers] Python 프로그래머스 주식가격 Level 2

728x90

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

 

코딩테스트 연습 - 주식가격

초 단위로 기록된 주식가격이 담긴 배열 prices가 매개변수로 주어질 때, 가격이 떨어지지 않은 기간은 몇 초인지를 return 하도록 solution 함수를 완성하세요. 제한사항 prices의 각 가격은 1 이상 10,00

programmers.co.kr

 

분류는 스택/큐로 구분되어있지만 사실 완전 탐색으로도 풀리는 문제다.

 

문제풀이


지문 자체가 어렵다는 사람들이 많은 것 같아서 문제를 좀 더 쉽게 설명하겠다.

 

prices의 가격들은 매초 변하는 가격을 뜻하고 가격이 떨어지지 않는 기간은 현재 가격보다 더 낮은 가격이 나온 시간까지 매초(가격의 수) 세면 된다는 뜻이다.

 

그래서 예시에서 \1은 그 뒤에 \1보다 낮은 시간이 없기 때문에 4초(4개의 가격) 동안 가격이 떨어지지 않는 것이고 마지막 \3은 그 뒤에 남아있는 시간이 없기 때문에 0초가 된 것이다.

 

단지 지문에서 "가격이 떨어지지 않은 기간은 몇 초인지"라고만 있었기에 이를 헷갈려서 질문에 올린 사람들이 많은 것 같다.

 

어려운 문제가 아니므로 바로 전체 코드로 넘어가겠다.

 

def solution(prices):
    answer = []
    for i in range(len(prices)):
        cnt=0
        for j in range(i+1,len(prices)):
            if prices[i]<=prices[j]:
                cnt+=1
            else:
                cnt+=1
                break
        answer.append(cnt)
    return answer

 

3번째 줄은 prices의 전체 범위를 탐색하겠다는 것을 뜻하고 5번째 줄은 현재 가격보다 떨어지는 시간이 나올 때까지 남은 시간을 반복하여 세는 반복문이다.

 

만약 현재 가격보다 낮은 시간이 있다면 그 뒤에 가격은 고려할 필요가 없기에 break를 통해 바로 반복문을 탈출하면 된다.

 

그렇게 카운트한 값을 answer에 추가하면 된다.

 

결과 화면
결과 화면

 

다만 의문인 점은 prices의 길이는 100,000(10만) 이하이고 완전 탐색은 O(n^2)의 시간 복잡도가 걸리므로 1초당 5천만~1억 정도 연산이 가능한 Python을 기준으로 최악의 테스트 케이스가 나온다면 시간 초과가 걸릴 수밖에 없다.

 

하지만 Input이 작은 정확성까진 이해가 됐으나 상당히 큰 Input이 들어오는 효율성까지 통과된 거로 봐서는 최악의 경우까진 Input이 들어오지 않게 설정한 것 같다.

728x90

댓글()

[BOJ] Python 백준 23746번 문자열 압축 해제 브론즈 1

728x90

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

 

23746번: 문자열 압축 해제

특정 소문자 문자열 패턴을 대문자 한 글자로 압축하는 프로그램 SPC(String Pattern Compressor)가 있다. 예를 들어, 다음과 같은 방법으로 압축하는 경우, “$\text{aabbaaac}$”는 “$\text{ABAC}$”로 압축된

www.acmicpc.net

 

문제 풀이


대문자 하나에 대응하는 소문자 문자열이 정해져 있으므로 Python의 딕셔너리를 사용하면 쉽게 해결할 수 있다.

 

대응하는 문자들을 딕셔너리에 저장하고 압축된 문자열이 들어왔을 때 차례대로 소문자 문자열로 치환하면 쉽게 풀 수 있는 문제다.

 

바로 전체 코드로 넘어가겠다.

 

n=int(input())
word={}
res=""
for i in range(n):
    temp=list(input().split())
    word[temp[1]]=temp[0]
question=input()

for i in question:
    res+=word[i]
num=list(map(int,input().split()))
print(res[num[0]-1:num[1]])

 

2번째 word는 딕셔너리를 선언했고 for문을 돌면서 입력받은 값을 저장하면 된다.

 

이때 주의해야 할 점은 압축된 문자열을 풀어야 하므로 입력받은 대문자를 딕셔너리의 키, 소문자 문자열 패턴을 딕셔너리의 값으로 저장해야 한다는 것이다.

 

res에 치환한 문자열을 저장하고 입력받은 인덱스를 기준으로 출력하면 쉽게 풀 수 있다.

 

인덱스로 범위 출력 시 왼쪽 인덱스는 포함, 오른쪽 인덱스는 미만까지 출력하는 점을 주의해야 한다.

 

결과 화면
결과 화면

 

728x90

댓글()

[Programmers] Python 프로그래머스 프린터 Level 2

728x90

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

 

코딩테스트 연습 - 프린터

일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린

programmers.co.kr

 

큐를 사용하면 쉽게 풀 수 있는 문제이다.

 

스택과 큐에 대해 익숙하지 않거나 까먹었다면 먼저 이전 포스팅을 참고하여 이해하고 오는 것을 추천한다.

2021.12.04 - [알고리즘/알고리즘 강의] - [알고리즘] 스택(Stack)과 큐(Queue) 데크(Deque)까지 (Python)

 

[알고리즘] 스택(Stack)과 큐(Queue) 데크(Deque)까지 (Python)

설명 자료구조(Data Structure)를 공부할 때 가장 처음 접하는 것은 스택(Stack)과 큐(Queue)다. 그전에 자료구조란 Data를 효율적으로 저장하고 접근하여 사용하는 방법을 뜻한다. 적합한 상황에 적절한

khsung0.tistory.com

 

문제풀이


눈여겨봐야 할 점은 3가지다.

 

  1. 대기목록에서 꺼낸 문서보다 중요도가 높은 문서가 대기목록에 남아있다면 꺼낸 문서를 다시 대기 목록에 넣는다.
  2. 대기 목록에는 최대 100개의 문서가 있다.
  3. 중요도는 숫자가 클수록 중요하다.

대기 목록인 priorities의 첫 원소를 차례대로 빼면서 나머지 원소 중 최대 중요도를 비교하여 뺀 문서보다 중요도 높은 문서가 있다면 뒤에 추가하는 형식으로 풀면 될 것이다.

 

이때 최대 100개의 문서밖에 없으므로 O(n)의 시간 복잡도를 가지는 max 함수로 최대 중요도를 비교하면 된다.

 

동시에 location에 해당하는 문서가 몇 번째에 출력되는지 묻는 문제이므로 원소를 pop 할 때마다 location을 감소시키고 음수가 되면 대기 목록의 마지막에 추가되었다고 생각하면 된다.

 

간단한 문제이므로 바로 전체 코드로 넘어가겠다.

 

def solution(priorities, location):
    answer = 0
    while len(priorities)>0:        #대기 목록에 문서가 있는 동안 반복
        temp=priorities.pop(0)      #첫 번째 문서 꺼내기
        if len(priorities)==0:      #껴낸 문서가 마지막 일때 종료
            answer+=1
        else:
            if temp>=max(priorities):   #꺼낸 문서의 중요도가 제일 높을 때
                if location==0:         #찾고자 하는 문서일 때 종료
                    answer+=1
                    break
                else:
                    location-=1
                    answer+=1
                        
            #꺼낸 문서보다 중요도가 높은 문서가 대기 목록에 존재할 때
            else:
                priorities.append(temp)
                location-=1
                if location<0:
                    location=len(priorities)-1
    return answer

 

3번째 줄은 대기 목록에 문서가 있는 동안 반복하기 위해 while문을 선언하였고  4번째 줄은 pop(0)을 통해 0번째 인덱스의 원소를 제거하며 반환한다.

 

또한 5번째 줄은 꺼낸 문서가 마지막 문서일 때 (더 이상 대기 목록에 문서가 없을 때) 고려할 조건이 없으므로 answer을 증가시킨 후 바로 종료한다.

 

8번째 줄의 if문은 max로 대기 목록의 중요도를 비교하여 더 높은 중요도가 없으면 출력하는 문서로 판단하고 location을 감소시킨다.

 

이때 location이 0이라면 꺼낸 문서가 찾는 문서이므로 answer을 증가시킨 뒤 break를 통해 반복문을 빠져나온다.

 

17번째 else는 대기 목록에 더 높은 중요도가 있을 때 뒤에 추가하는 구문으로 만약 location이 음수가 되면 대기 목록의 마지막에 추가했다는 의미이므로 현재 priorities 길이의 -1로 변경하면 된다.

 

결과 화면
결과 화면

 

이 문제는 Input Size가 상당히 작아서 굳이 시간 복잡도를 계산할 필요까진 없었던 것 같다.

 

조건만 잘 확인하고 구현한다면 충분히 쉽게 통과할 수 있을 것이다.

 

이 프린터 문제는 우선순위 큐란 알고리즘이다.

 

다만 우선순위 큐는 힙(Heap)이란 자료 구조를 사용하고 내부 구조에서 최댓값, 최솟값을 갱신하는데 O(logn)의 효율적인 시간 복잡도를 가진다.

 

파이썬은 Heapq란 모듈을 통해 쉽게 우선순위 큐를 구현 가능하며 해당 문제에서는 큐를 연습하기 위해 일부러 Input을 적게 주고 우선순위 큐의 결과를 나타낼 수 있도록 유도한 것 같다.

 

코테에서도 은근히 우선순위 큐를 사용하는 문제가 나오므로 우선순위 큐를 구현하는 힙에 대해서 포스팅하겠다.

728x90

댓글()

[Programmers] Python 프로그래머스 기능개발 Level 2

728x90

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

 

코딩테스트 연습 - 기능개발

프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다. 또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는

programmers.co.kr

 

프로그래머스의 분류에도 나와 있듯이 큐를 사용하면 쉽게 풀 수 있는 문제이다.

 

스택과 큐에 대해 익숙하지 않거나 까먹었다면 먼저 이전 포스팅을 참고하여 이해하고 오는 것을 추천한다.

 

https://khsung0.tistory.com/14?category=1038750 

 

[알고리즘] 스택(Stack)과 큐(Queue) 데크(Deque)까지 (Python)

설명 자료구조(Data Structure)를 공부할 때 가장 처음 접하는 것은 스택(Stack)과 큐(Queue)다. 그전에 자료구조란 Data를 효율적으로 저장하고 접근하여 사용하는 방법을 뜻한다. 적합한 상황에 적절한

khsung0.tistory.com

 

문제 풀이


눈여겨봐야 할 점은 5가지다.

 

  1. 작업의 개수는 100개 이하
  2. 작업 진도는 100 미만의 자연수
  3. 작업 속도는 100 이하의 자연수
  4. progresses의 순서대로 배포한다.
  5. 배포는 하루에 한 번만 이루어진다.

 

문제를 보자마자 떠올린 생각은 day를 하루씩 증가시키면서 progresses 리스트에 speeds 리스트의 원소를 계속 더하고 progresses의 길이가 0이 될 때까지 같은 날에 0번째 인덱스의 원소가 100 이상이면 pop 하면서 카운트하여 answer에 추가하는 방식이었다.

 

애초에 작업의 개수가 100개 이하고 작업 진도가 1, 작업 속도가 1일 때 최대 99일이므로 Input이 작아 가능성은 있어 보였다.

 

하지만 Python의 pop함수에서 0번째 인덱스를 제거하는 pop(0)은 O(n)의 시간 복잡도를 가지므로 원소를 제거하는 과정에서 추가적으로 불필요한 연산이 생기기에 상당히 비효율적인 방식이라 다른 방법을 생각해봤다.

 

그 결과 굳이 매번 원소들을 더하는 게 아니라 day를 증가시키면서 같은 day일 경우를 카운트하여 answer에 추가하고 기존의 리스트에 대한 변경 없이 현재 어떤 인덱스를 가리키는지 알려주는 curr_index를 선언한다면 매번 원소를 제거할 때 드는 시간 복잡도도 없어질 것이라 판단하였다.

 

전체 코드를 통해 설명하면 이해가 더 빠를 것이다.

 

def solution(progresses, speeds):
    answer = []
    day=0           #개발 일수
    curr_index=0    #현재 작업 Index

    #작업 Index를 0번 부터 끝까지 반복
    while curr_index<len(progresses):

        #현재 작업이 100% 넘을 때까지 day 증가
        while progresses[curr_index]+speeds[curr_index]*day<100:
            day+=1

        #완료된 작업 개수 카운트
        cnt=0

        #완료된 작업 카운트
        while curr_index<len(progresses) and progresses[curr_index]+speeds[curr_index]*day>=100:
            cnt+=1
            curr_index+=1
        answer.append(cnt)
    return answer

 

7번째 줄을 통해 progresses 리스트를 전체 반복하고 10번째 줄을 통해 현재 작업이 100%가 될 때까지 day를 증가시킨다.

 

day를 찾으면 같은 날일 때 몇 개의 작업을 배포할 수 있는지 세기 위해 14번째 줄에 cnt를 선언하여 0으로 초기화한다.

 

초기화된 cnt를 기반으로 17번째 줄에서 배포 가능한 작업들을 세며 curr_index를 증가시킨다.

 

이때 while문에서 curr_index<len(progresses)를 먼저 선언한 이유는 curr_index가 증가할 때 progresses의 리스트 범위를 벗어나 Index Error를 일으킬 수 있기 때문이다.

 

프로그래밍 언어에서 조건을 판단할 때 앞에 있는 조건이 False라면 뒤에 있는 조건을 확인하지 않기 때문에 이처럼 Index Error를 방지하는 조건이나 시간 복잡도를 최대한 줄일 수 있는 조건은 되도록이면 앞에 쓰는 습관을 들이자.

 

마지막으로 카운트한 작업 수를 answer에 추가하면 끝이다.

 

결과 화면
결과 화면

 

이렇게 구현한 방식은 리스트의 원소를 제거하는 등 불필요한 연산을 줄였기 때문에 day를 증가시키는 연산(최대 99번), progresses 리스트를 탐색하는 연산(최대 100번)을 하면 최대 약 10,000번의 연산을 한다.

 

엄밀히 말하자면 큐로 푼 게 아니라 리스트의 인덱스 접근을 통해 풀었고 처음에는 상당히 비효율적인 방식을 생각했었다.

 

항상 문제의 조건을 정확히 파악하여 자신이 생각한 방식의 시간 복잡도를 계산해보고 보다 더 효율적인 방식이 있는지 끊임없이 고민하는 습관이 상당히 중요한 것 같다.

 

 

728x90

댓글()

[자료구조] 스택(Stack)과 큐(Queue) 데크(Deque)까지 (Python)

728x90

설명


자료구조(Data Structure)를 공부할 때 가장 처음 접하는 것은 스택(Stack)과 큐(Queue)다.

 

그전에 자료구조란 Data를 효율적으로 저장하고 접근하여 사용하는 방법을 뜻한다.

 

적합한 상황에 적절한 자료구조를 사용하면 아주 효율적인 알고리즘을 사용할 수 있는 장점이 있다.

 

이번 시간에 가장 기본 중에 기본인 스택과 큐에 대해 알아보겠다.

 

스택 (Stack)


먼저 스택은 나중에 들어오는 Data가 먼저 나가는 LIFO(Last In First Out) 형태이다.

 

통에다가 블록을 넣고 빼는 방식을 연상하면 이해가 쉬울 것이다.

 

Data를 넣는 연산은 Push라고 한다.

 

Push 연산 결과
Push 연산 결과

 

반대로 Data를 빼는 연산은 Pop이라고 한다.

 

Pop 연산 결과
Pop 연산 결과

 

그림을 통해 쉽게 이해할 수 있듯이 나중에 들어간 Data가 먼저 나오고 먼저 들어간 Data가 나중에 나오는 자료구조를 스택이라고 표현한다.

 

만약 C 같이 다른 언어였다면 구조체를 선언하여 현재 얼마나 Data가 들어왔는지 판단하는 Top이란 변수를 통해 구현하겠지만 Python은 그럴 필요가 없다.

 

보통 라이브러리를 사용하는 경우를 제외하면 구현의 편의성을 위해 배열을 미리 선언(정적 할당)하고 잘못된 인덱스로 접근하는 Index Error를 방지하기 위해 Top이란 변수를 선언하여 오류를 방지한다.

 

또한 필요하다면 배열의 크기를 변경하는 복잡한 과정을 거쳐야 한다.

 

하지만 Python은 배열이 아닌 리스트를 지원하기 때문에 비교적 Data 추가 삭제에 대한 고민을 덜 수 있다.

 

큐 (Queue)


다음은 큐다.

 

큐는 먼저 들어온 Data가 먼저 나가는 FIFO(First In First Out) 형태이다.

 

즉, 차례대로 줄을 서서 기다리는 형태를 생각하면 된다.

 

큐에서 Data를 넣는 연산은 Enqueue라고 한다.

 

Enqueue 연산 결과
Enqueue 연산 결과

 

Data를 빼는 연산은 Dequeue라고 한다.

 

스택과는 다르게 먼저 들어간 Data가 먼저 빠지는 것을 확인할 수 있다.

 

Dequeue 연산 결과
Dequeue 연산 결과

 

구현


Python은 앞서 말한 대로 배열이 아닌 리스트를 지원하기 때문에 리스트와 관련되어 지원하는 함수들로 아주 쉽게 스택과 큐를 구현 가능하다.

 

여러 가지 함수들이 있지만 구현하는데 필요한 함수는 append()와 pop()이다.

 

각각 뒤에 원소를 추가하고 빼는 함수인데 pop(x)처럼 안에 인자를 넣으면 x번째 원소를 반환하고 제거한다는 의미이다.

 

이를 이용하여 x에 0을 넣으면 0번째 원소를 제거하므로 쉽게 큐를 구현할 수 있다.

 

다음은 앞서 설명한 과정을 그대로 구현한 전체 코드이다.

 

stack=[]    #스택 선언
print("현재 스택 :",stack)
stack.append(1)     # 1 추가
print("현재 스택 :",stack)
stack.append(2)     # 2 추가
print("현재 스택 :",stack)
stack.pop()         #끝 원소 하나 제거
print("현재 스택 :",stack)
stack.pop()         #끝 원소 하나 제거
print("현재 스택 :",stack, end="\n\n")

queue=[]    #큐 선언
print("현재 큐 :",queue)
queue.append(1)     # 1 추가
print("현재 큐 :",queue)
queue.append(2)     # 2 추가
print("현재 큐 :",queue)
queue.pop(0)         #첫 원소 하나 제거
print("현재 큐 :",queue)
queue.pop(0)         #첫 원소 하나 제거
print("현재 큐 :",queue)

 

결과 화면
결과 화면

 

복잡한 과정 없이 함수 두 개로 간단하게 구현하였으며 보통 그래프 탐색에서 스택은 깊이 우선 탐색(DFS), 큐는 너비 우선 탐색(BFS)에 자주 쓰인다.

 

따라서 코테준비를 위해 상당히 자주 사용할 문법이므로 알아야 한다.

 

데크 (Deque)


사실 큐는 구현 방법에 따라 다양한 이름이 있는데 가장 단순한 큐(Queue), 배열의 비효율성을 개선하기 위한 원형 큐(Circular Queue), 앞과 뒤 둘 다 Data를 넣고 뺄 수 있는 데크(Deque), 자료구조 중 하나인 힙(Heap)을 이용한 우선순위 큐(Priority Queue) 이런 식으로 장단점을 개선한 방식이 존재한다.

 

Python의 특성 상 원형 큐는 구현할 필요가 없고 우선순위 큐는 파이썬의 모듈 중 하나인 heapq를 사용하면 된다.

 

이번에 추가적으로 설명할 자료구조는 데크다.

 

데크 혹은 덱이라 부르는데 이 자료구조는 앞과 뒤에서 Enqueue와 Dequeue가 가능하다.

 

Deque 연산
Deque 연산

 

파이썬의 pop()은 O(1)의 시간 복잡도가 들지만 첫 번째 원소를 제거하기 위해 pop(0)을 사용하게 되면 끝에서부터 원소를 찾기에 O(n)의 시간 복잡도가 걸린다.

 

따라서 Input이 너무 큰 상황이라면 효율을 위해 데크를 사용하여 시간 복잡도를 줄일 수 있다.

 

주요 함수는 append(), appendleft(), pop(), popleft()이고 left가 붙으면 첫 번째에, 붙지 않으면 마지막에 적용된다.

 

데크 구현


다음은 데크의 연산 과정을 확인할 수 있는 전체 코드이다.

 

from collections import deque   #데크 모듈 선언
deque=deque()
print("현재 데크 :",deque)
deque.append(1)         #오른쪽에 1 추가
print("현재 데크 :",deque)
deque.appendleft(2)     #왼쪽에 2 추가
print("현재 데크 :",deque)
deque.popleft()         #첫 번째 원소 제거
print("현재 데크 :",deque)
deque.pop()             #끝 원소 제거
print("현재 데크 :",deque)

 

결과 화면
결과 화면

 

처음 보면 모듈 선언이 다소 어려울 수 있겠지만 익숙해진다면 그냥 리스트로 구현하는 것보다 시간 복잡도적으로 유리한 구현이 가능해진다.

 

스택과 큐를 연습할 수 있는 문제를 추천하며 마무리 짓겠다.

 

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

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

 

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

 

10845번: 큐

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net

728x90

댓글()

[알고리즘] 이진탐색 / 이분탐색 (Binary Search) (Python)

728x90

보통 원하는 원소를 찾고자 할 때 처음부터 끝까지 탐색하는 선형 탐색을 주로 사용한다.

 

선형 탐색은 데이터의 크기가 너무 크지 않다면 딱히 고려할 조건이 없기 때문에 구현이 쉽기 때문이다.

 

하지만 데이터의 크기가 너무 커진다면 얘기가 달라진다.

 

그래서 나온 탐색 방법이 이진 탐색이다.(이분 탐색도 같은 말)

 

먼저 기본적인 개념은 순차적으로 정렬이 된 상태에서 특정 원소를 찾을 때까지 범위를 절반씩 줄이고 더 이상 찾을 범위가 없으면 해당 원소는 없다고 판단하는 알고리즘이다.

 

N개의 Data가 있을 때 범위를 절반씩 줄여나가므로 O(logn)의 아주 효율적인 시간 복잡도를 가지는데 여기서 중요한 점은 정렬된 상태여야 한다는 것이다.

 

왜냐하면 범위를 줄여나갈 때 찾고자 하는 원소와 현재 범위의 중간값을 비교해서 일치하면 중단, 일치하지 않으면 절반에 해당하는 범위엔 찾고자 하는 원소가 없다는 전제하에 범위를 줄여나가는 방식인데 정렬된 상태가 아니라면 이처럼 범위를 줄여나갈 수가 없다.

 

따라서 정렬된 Data를 탐색하거나 정렬하여 탐색할 수 있는 범위가 주어진다.

 

참고로 Python의 sort함수를 쓰면 O(nlogn)의 시간 복잡도를 가지므로 100만의 Input정도는 충분히 정렬 후 탐색할 수 있다.

 

그림의 예시를 따라가다 보면 쉽게 이해할 수 있을 것이다. (예시는 오름차순 리스트를 하며 내림차순은 반대로 하면 된다)

 

data=[1&#44;2&#44;4&#44;5&#44;6&#44;8&#44;9]
data=[1,2,4,5,6,8,9]

 

먼저 리스트의 전체 범위에서 시작해야 하므로 Left와 Right 두 개의 변수가 필요하다.

 

Left는 시작을 뜻하는 0(0번째 인덱스), Right는 끝을 뜻하는 len(data)-1로 선언하면 된다.

 

Left와 Right 변수 선언
Left와 Right 변수 선언

 

이제 아주 간단한 사전 준비는 끝났다.

 

Left와 Right의 위치가 역전된다면 더 이상 탐색할 범위가 없다는 뜻이므로 Left <= Right인 동안 반복을 계속 돌려주면 된다.

 

예시로 2와 7을 찾도록 해보겠다.

 

중앙값 비교
중앙값 비교

 

빨간색 화살표는 중앙값(변수명은 mid)을 뜻하고 찾고자 하는 원소가 mid에 있는 원소보다 작으므로 왼쪽 범위를 찾아야 한다는 뜻이 된다.

 

이때 이미 mid에 위치한 원소는 탐색했으므로 Right는 mid-1로 변경해서 조금이라도 탐색 횟수를 줄여준다.

 

범위 줄인 뒤 중앙값 비교
범위 줄인 뒤 중앙값 비교

 

Right=mid-1로 범위를 바꾼 뒤 다시 중앙값(mid)을 비교해보면 2를 찾을 수 있다.

 

해당 위치의 인덱스를 저장한 뒤 반복문을 빠져나오면 된다.

 

다음은 리스트에 없는 7을 찾아보겠다.

 

중앙값 비교
중앙값 비교

 

찾고자 하는 원소가 중앙값보다 크므로 오른쪽 범위에 있단 의미고 마찬가지로 중앙값은 탐색했으므로 탐색 횟수를 줄이기 위해 Left는 mid+1로 변경한다.

 

범위 줄인 뒤 중앙값 비교
범위 줄인 뒤 중앙값 비교

 

오른쪽 범위로 이동해서 다시 중앙값을 비교해보니 찾고자 하는 원소보다 중앙값이 더 크다.

 

이 말은 왼쪽 범위에 있단 뜻이므로 Right를 mid-1로 변경한다.

 

범위 줄인 뒤 중앙값 비교
범위 줄인 뒤 중앙값 비교

 

다시 왼쪽 범위로 이동해서 중앙값을 비교해보니 찾고자 하는 원소가 중앙값보다 더 크다.

 

이 말은 중앙값보다 오른쪽 범위에 있단 뜻이므로 Left는 mid+1로 변경한다.

 

이때 Left는 Right보다 커져서 역전되므로 결국 원소를 찾지 못한 채 반복문을 빠져나오게 된다.

 

이 알고리즘이 이진 탐색이며 7개의 Data에서 2를 찾는데 2번 연산, 7이 있는지 확인하는데 3번 연산밖에 하지 않았다.

 

만약 선형 탐색이었다면 최악의 경우 7번(Data의 크기만큼)의 연산을 할 것이고 확실히 이진 탐색을 통해 연산 횟수가 줄어든 것을 알 수 있다.

 

지금은 Data의 크기가 작기 때문에 몇 번 차이가 없지만 Data의 크기가 막대하게 커지면 상당히 효율적인 알고리즘이란 사실을 체감할 수 있을 것이다.

 

다음은 위의 설명대로 구현한 전체 코드이다.

 

data=[1,2,4,5,6,8,9]

def binary(n):
    index=-1
    left=0
    right=len(data)-1
    
    print("이진 탐색 과정 :",end=" ")

    while left<=right:
        mid=(left+right)//2
        print(data[mid],end=" ")
        if data[mid]==n:
            index=mid
            break
        elif n<data[mid]:
            right=mid-1
        else:
            left=mid+1
    print()
    return index

first=binary(2)

if first==-1:
    print("없는 원소입니다.")
else:
    print(first,"번째 인덱스에 있습니다.")

second=binary(7)

if second==-1:
    print("없는 원소입니다.")
else:
    print(second,"번째 인덱스에 있습니다.")

 

초기 Index는 -1로 지정하고 찾는 원소가 있다면 해당 원소의 인덱스로 갱신한다.

 

즉 여전히 Index가 -1이라면 찾는 원소가 없단 뜻이다.

 

결과 화면
결과 화면

 

그림을 참고하여 코드를 한 줄씩 따라가다 보면 쉽게 이해할 수 있을 것이다.

 

혹시나 해서 알고리즘 구현 자체를 접한 지 얼마 안 된 사람들께 덧붙이자면 이번 코드에서는 예시를 위해 인덱스를 반환하도록 구현했지만 당연하게도 각자 접하는 문제에 맞게끔 변형하여 구현해야 된다.

 

끝으로 이진탐색을 연습할 수 있는 문제를 몇가지 추천한다.

 

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

 

1920번: 수 찾기

첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들

www.acmicpc.net

 

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

 

1654번: 랜선 자르기

첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그

www.acmicpc.net

728x90

댓글()

[코딩 테스트] 2021 엔픽셀 NPIXEL 신입공채 코딩 테스트 후기 (불합격)

취업 과정|2021. 12. 1. 19:37
728x90

엔픽셀 공고 이미지
엔픽셀 공고 이미지

 

지난 2021.11.19(금)에 엔픽셀(NPIXEL) 코딩 테스트를 봤다.

 

엔픽셀(NPIXEL)은 모바일 게임 그랑사가를 출시한 회사이며 최단기간 유니콘 기업에 등극한 기업이다.

 

이때 유니콘 기업이란 기업 가치 10억 달러 이상, 창업한 지 10년 이하인 비상장 스타트업을 뜻하며 흔히 아는 크래프톤, 비바리퍼블리카(토스), 야놀자, 위메프, 쏘카, 무신사 등이 유니콘 기업에 속한다.

 

공채 사이트에서 Next Pixels 1기란 문구를 봐선 아무래도 첫 공채인 것 같다.

 

조금 신기했던 게 메일이나 문자 내용에서 이모티콘이 상당히 많은 것으로 보아 단순 업무로 딱딱한 내용을 전송하는 게 아니라 지원자들에게 친근하게 다가가고 싶어 하는 것처럼 느껴졌다.

 

또한 코테가 끝나면 1만원 상당의 스타벅스 기프티콘도 보내주더라.(프로그래밍 직군은 코테고 다른 직군은 과제 전형 끝나면 주는 듯??)

 

각설하고 프로그래밍 직군은 과제 전형 기간에 포트폴리오로 제출 가능한 Github 주소나 링크가 있으면 제출 가능했다.

 

이때 링크는 메모장에 작성해서 Zip 파일로 압축하여 올리는 거라 난 Github 주소와 포트폴리오 사이트 주소를 같이 제출했다.

 

그리고 코테는 다소 특이한 방식으로 진행됐다.

 

11.19(금) 오전 10시 ~ 11.21(일) 오후 10시 *총 3일간 아무 때나 편할 때 접속해서 응시하면 되고 총 4문제, 3시간 동안 보면 됐다.

 

이렇게 특정 기간 동안 자유롭게 코테를 볼 수 있는 것은 삼성 SDS에서 주관한 2021 하계 대학생 알고리즘 특강을 위한 코테를 제외하곤 처음이다.

 

플랫폼은 프로그래머스에서 진행됐고 1~2번은 반드시 C++로만, 3~4번은 C++ 또는 Python을 선택해서 풀 수 있었다.

 

문제별로 언어가 제한되는 것도 특이한 경험이긴 했다.

 

게임회사다 보니까 언어를 C++과 Python으로만 제한해서 보는 것 같은데 다행히 난 C를 할 줄 알아서 비교적 어렵진 않게 C++문법을 한 번 훑고 필요할만한 라이브러리도 정리하고 첫날 바로 코테를 봤다.

 

젤 중요한 코테의 난이도는 여러 알고리즘을 접해봤다면 어렵진 않게 풀 수 있는 수준이다.

 

알고리즘을 분류하자면 구현, 그래프, DP 정도가 나왔는데 어렵게 꼬아놓은 형식이 아니라 해당 알고리즘들을 접해봤다면 시간도 넉넉해서 충분히 풀 수 있는 문제였다.

 

하지만 난 결국 한 문제를 풀지 못했다.....ㅠㅠ

DP문제였는데 점화식을 세우는 과정에서 머리가 안 돌아가더라.....

어차피 공채가 있길래 넣어본 거라 머리가 안 돌아가서 그냥 3문제 푼 거에 만족하고 껐다.

 

근데 쉬었다가 한 번 다시 세워보니 금방 나왔다.

 

결과


결과가 나왔는데 불합격 메일이 왔다. (2021.12.02)

 

결과 메일
결과 메일

 

공채 단톡방을 확인해보니 3문제 풀고 합격한 사람도 있고 4문제 풀고 떨어진 사람도 있다고 한다.

 

여태 경험한 코테들은 상위 점수별로 합격을 시키고 동점자가 많은 커트라인은 자소서를 기반으로 합, 불을 정했는데 이번 코테는 어떤 기준인지 감이 잡히지 않았다.

 

여러 가지 가능성을 추측해보자면

 

  1. 시간 복잡도의 제한으로 인해 효율적인 알고리즘만 통과했다.
  2. 기존 테스트 케이스로 조건을 거르지 못하는 예상치 못한 히든 테스트 케이스가 존재했다.
  3. 제출한 포트폴리오가 영향을 끼친다.
  4. 결과뿐만 아니라 작성한 코드에도 평가요소가 있다.

이 정도가 떠오른다.

 

1. 분명 Input과 알고리즘의 시간 복잡도를 계산하면서 구현했지만 아무래도 사람인지라 충분히 실수할 가능성은 있다.

 

2. 히든 테케도 같은 원리이다.

 

3. Github주소와 포트폴리오 사이트를 제출했고 해당 사항은 선택이었지만 점수에 들어갈 가능성을 배제할 순 없다.

 

4. 이는 라인(Line)에서 진행한 코테 방식인데 평가요소에 들어간다고 명시해야 합리적인 방식이다. 따라서 이 부분은 비교적 가능성이 낮아 보인다.

 

어찌 됐든 내 실력이 부족하여 탈락한 것이므로 어디서든 합격할 수 있게 철저히 준비해야겠다.

728x90

댓글()

[SSAFY] 싸피 7기 SW 적성 진단 후기(합격)

취업 과정|2021. 12. 1. 14:39
728x90

지난 2021.11.13에 SW 적성 진단을 보고
오늘 (2021.11.29) 결과가 나왔다.

 

적성 진단 결과
적성 진단 결과


지난 4기, 6기에도 지원해본 경험으로 보면 이번 7기 SW 적성 진단은 비교적 쉬운 편이었다.

SW 적성 진단은 수리/추리 문제, Computational Thinking(CT) 이렇게 두 가지로 나눠진다.

수리/추리 문제는 15문항, CT는 큰 문제는 5문항, 각 문제는 5문항씩 점점 Input이 증가하는 형태이다.

4기, 6기 때는 CT가 30분이었으며 수리/추리 문제를 약 75% 정도 풀었고 CT는 40% 정도 풀었었는데 둘 다 적성 진단은 합격했었다.

CT를 40% 정도 푼 것도 어려워서가 아니라 시간이 부족해서였다.

하지만 이번에는 CT가 10분이 늘어났고 난이도 자체도 엄청 쉬워져서 수리/추리 문제는 75% 정도, CT는 100% 풀었고 합격할 것이란 예상은 틀리지 않았다.

과거 Interview 경험을 기반으로 이번엔 부족한 부분을 싸피를 통해 배워야겠다는 의지를 어필해야겠다.

분명 Interview에서 면접관님께 "아시는 것도 많은 것 같네요"란 말을 들었지만 불합격한건, 싸피 자체가 취업시장 활성화를 위한 능력있는 개발자 배출을 목표로 하기에 보다 더 배움이 필요한 지원자가 적합하기 때문에 떨어진 것 같다.

SW 적성 진단 합격 팁은 수리/추리 문제는 NCS의 자료 해석과 방정식을 세우는 수학 문제를 여러 번 풀어보고 논리적으로 추리 문제를 해결하는 연습을 하면 될 것이다.

또한 전공자라면 CT가 시간과의 싸움일 뿐 문제 자체가 어렵진 않겠지만 비전공자라면 알고리즘을 공부하고 백준이나 프로그래머스에서 간단한 알고리즘 문제를 접하면 쉽게 풀 수 있을 것이라 생각한다.

알고리즘 문제 자체가 컴퓨팅 사고이기 때문이다.

백준과 프로그래머스는 알고리즘을 코드로 구현하는 연습을 하는 사이트이고 IT기업 입사를 위해 가장 기본적으로 보는 코딩 테스트 합격을 위해 필수인 사이트이다.

https://www.acmicpc.net/

 

Baekjoon Online Judge

Baekjoon Online Judge 프로그래밍 문제를 풀고 온라인으로 채점받을 수 있는 곳입니다.

www.acmicpc.net


https://programmers.co.kr/learn/challenges

 

코딩테스트 연습

기초부터 차근차근, 직접 코드를 작성해 보세요.

programmers.co.kr


백준에 Solved.ac란 기능이 있는데 이를 기준으로 골드 티어, 프로그래머스는 3단계 정도 실력이 되면 대부분의 기업 코딩 테스트는 합격할 수준이 될 것이다.

현재 작성자는 골드 2 수준으로 네이버, 라인과 같은 IT기업 코테에 합격한 경험이 있다.

728x90

댓글()