codility 4-1. FrogRiverOne

|

문제출처

예전에 2시간을 고민하고도 풀지 못했던 문제였다.
한달이 지나고 나서 다시 풀어보았는데, 시간복잡도 O(N^2)로 풀었다가 시간복잡도 O(N)으로 성능 개선하는데 성공했다. 너무 뿌듯하다!! :)


문제

A small frog wants to get to the other side of a river. The frog is initially located on one bank of the river (position 0) and wants to get to the opposite bank (position X+1). Leaves fall from a tree onto the surface of the river.

You are given a zero-indexed array A consisting of N integers representing the falling leaves. A[K] represents the position where one leaf falls at time K, measured in seconds.

The goal is to find the earliest time when the frog can jump to the other side of the river. The frog can cross only when leaves appear at every position across the river from 1 to X (that is, we want to find the earliest moment when all the positions from 1 to X are covered by leaves). You may assume that the speed of the current in the river is negligibly small, i.e. the leaves do not change their positions once they fall in the river.

For example, you are given integer X = 5 and array A such that:

  A[0] = 1
  A[1] = 3
  A[2] = 1
  A[3] = 4
  A[4] = 2
  A[5] = 3
  A[6] = 5
  A[7] = 4
In second 6, a leaf falls into position 5. This is the earliest time when leaves appear in every position across the river.

Write a function:

def solution(X, A)
that, given a non-empty zero-indexed array A consisting of N integers and integer X, returns the earliest time when the frog can jump to the other side of the river.

If the frog is never able to jump to the other side of the river, the function should return −1.

For example, given X = 5 and array A such that:

  A[0] = 1
  A[1] = 3
  A[2] = 1
  A[3] = 4
  A[4] = 2
  A[5] = 3
  A[6] = 5
  A[7] = 4
the function should return 6, as explained above.

Assume that:

N and X are integers within the range [1..100,000];
each element of array A is an integer within the range [1..X].
Complexity:

expected worst-case time complexity is O(N);
expected worst-case space complexity is O(X), beyond input storage (not counting the storage required for input arguments).

풀이코드

첫번째 시도

  • 시간복잡도 : O(N ** 2)
  • for loop 안에서 A in B 검색을 사용해서 O(N**2) 시간복잡도
def solution(X, A):
    check = [False] * X
    for idx, val in enumerate(A):
        check[val-1] = True
        if not False in check:
            return idx
    return -1   

두번째 시도

  • 시간복잡도 : O(N)
  • A in B 검색을 사용하지 않기 위해서 별도의 check_sum 변수를 활용
def solution(X, A):
    check = [0] * X
    check_sum = 0
    for i in range(len(A)):
        if check[A[i]-1] == 0:
            check[A[i]-1] = 1
            check_sum += 1
            if check_sum == X:
                return i
    return -1

170529-0604_TIL

|

6월 4일 (일)

오늘 한 일

  • 박재성님의 vi를 효과적으로 연습하는 방법 영상을 보고 vimgolf 를 활용해서 vim을 연습했다.
    • vimgolf는 vim을 활용하여 가장 적은 타자수로 문서를 변경하는 게임이다. 1) 필요에 의해서 (문제를 풀기 위해서) 찾아서 배우게 된다는 점, 2)잘하는 다른 사람의 답변을 참고할 수 있다는 점 3) 짧고 간단해서 시간이 오래 걸리지 않는다는 점이 마음에 들었다.
    • SLiPP에 올라온 vi를 효과적으로 연습하는 방법은?에 더 다양한 연습방법에 대한 조언들이 있다.
  • 생활코딩의 Java 강의를 듣기 시작했다. 이왕 시작했으니 길어도 일주일 안에는 문법을 전체적으로 익혀봐야지.

6월 3일 (토)

오늘 한 일


6월 2일 (금)

오늘 한 일

  • 괜찮아보이는 알고리즘 책을 발견했다. 한빛 출판사에서 나온 Hello Coding 그림으로 개념을 이해하는 알고리즘 인데, 미리보기를 읽어보니 현실세계에서의 예시를 들어 쉽게 공감가도록 LinkedList와 Array가 설명되어 있었다. 읽어봐야지! :)
  • 파이썬의 코루틴과 제너레이터에 대해서 공부했다.
    • Generator는 연속된 (Sequence) 값들을 생산해내는 함수
    • 함수에 yield 키워드가 사용되면 Generator
    • yield한 값들이 순차적으로 생산된다.
    • Generator는 iterator이며, 항상 순회가능(iterable) 하다
    • Generator에서 return 문을 만나더라도 종료만 될 뿐, 리턴값이 사용 되지는 않는다.
    • list(range(100)) : 한번에 list를 생성
    • range(100) : 값을 그때그때 생성하여 yield

6월 1일 (목)

오늘 한 일


5월 31일 (수)

오늘 한 일


5월 30일 (화)

오늘 한 일

  • 과거에 풀었던 알고리즘 문제들을 다시 풀었다.
    • 예전에 2시간을 고민하고도 해결하지 못했던 문제를 한 달만에 다시 풀어보고 성공했다. 심지어 시간복잡도 O(n)으로 풀어서 정말 기분이 좋았다. 그래도 그동안 조금은 발전했구나!

내일 할 일

  • 알고리즘 문제 풀기
  • 컴퓨터 공학 강의노트 읽기

5월 29일 (월)

오늘 한 일

내일 할 일

알고리즘, 자료구조 여러가지 메모

|

기본 알고리즘

알고리즘

알고리즘 이란 어떤 값을 입력으로 받아 원하는 값으로 출력하는 잘 정의된 계산 절차 를 말한다. 따라서 알고리즘은 어떤 입력을 어떤 출력으로 변환하는 일련의 계산 과정이라 할 수 있다.

자료구조

자료구조 란 데이터에 편리하게 접근하고, 변경하기 위해서 데이터를 저장하거나 조직하는 방법 을 말한다. 모든 목적에 맞는 자료구조는 없다. 따라서 각 자료구조가 갖는 장점과 한계를 잘 아는 것이 중요하다.

자료구조의 미션 : 메모리의 효율적인 사용

  • 컴퓨터에는 3가지 중요한 부품이 존재하며 다음과 같은 특성을 가진다.
    • CPU : 중앙정보처리장치, 레지스터, 데이터를 연산/처리하는 가장 중요한 부분, 아주 빠름 (기억 떠올리기)
    • 메모리 : RAM(Random Access Memory), CPU에서 직접 접근이 가능, 사용자가 자유롭게 내용을 읽고 쓰고 지울 수 있다. 휘발성 기억장치, 빠름 (책에서 특정한 내용 찾아 읽기)
    • 스토리지 : HDD, SSD, 비휘발성 기억장치, 용량이 아주 크지만 느림 (지구를 한바퀴 돌아서 찾기)
  • 상기와 같은 이유로 데이터는 기본적으로 스토리지에 저장된다.
  • 하지만 스토리지는 매우 느리기 때문에 CPU와 함께 일하기에는 속도면에서 부족하다.
  • 따라서 어떤 프로그램을 실행하면 해당 프로그램과 데이터는 메모리로 옮겨진다.
  • CPU는 메모리에 로드된 데이터를 이용해서 여러가지 일을 하게 된다.
  • 그러므로 실행속도를 결정하는 것은 대체로 메모리 이며, 자료구조를 배우는 이유는 메모리의 효율적인 사용 이라고 할 수 있다. 2917

정렬

정렬은 아래와 같은 이유로 알고리즘 연구에서 가장 기본적인 문제로 여겨지고 있다.

  • 정보를 정렬하는 것 자체가 필요한 응용 분야가 있다. (ex. 은행의 고객 청구서)
  • 정렬을 핵심 서브 루틴으로 사용하는 알고리즘이 많다. (ex. 바이너리 서치)
  • 정렬은 역사가 길고, 기술도 풍부하다. 역사가 긴 정렬 알고리즘에는 중요한 기술이 포함되어 있다.
  • 정렬 알고리즘 구현시 여러 공학적 논쟁점이 나타난다. (캐시와 가상 메모리 등 메모리 계층구조)

힙정렬과 우선순위 큐

힙은 데이터에서 최대값 (혹은 최소값)을 빠르게 찾아내도록 만들어진 자료구조 이다.
힙은 완전이진트리에 기반한 자료구조로, 부모노드와 자식노드의 대소관계에 따라 최소힙 / 최대힙으로 구분된다. (힙이란 완전 이진트리에 있는 노드 중에서 키 값이 가장 큰 노드나, 키 값이 가장 작은 노드를 찾기 위해서 만든 자료구조)

힙정렬

  • 힙 정렬(Heapsort)이란 최대 힙 트리나 최소 힙 트리를 구성해 정렬을 하는 방법으로서,
    내림차순 정렬을 위해서는 최대 힙을 구성하고 오름차순 정렬을 위해서는 최소 힙을 구성하면 된다.
  • 힙 정렬이 가장 유용한 경우는, 전체 자료를 정렬하는 것이 아니라 가장 큰 값 몇개만 필요할 때이다.
  • 힙 정렬은 훌륭한 알고리즘이지만 퀵정렬이 일반적으로 더 빠르다. - 시간복잡도 O(n log n)
  • 하지만 힙은 그 자체로 대단히 쓸만한 자료구조이며, 대표적으로 우선순위 큐 구현시에 힙이 사용된다.

우선순위 큐

  • 우선순위를 가진 항목들을 저장하는 큐, 입력순서와 상관없이 우선순위가 높은 데이터가 가장 먼저 처리된다.
  • 선입선출 개념에서 약간 변형을 한것으로 나중에 들어왔지만, 먼저 처리해야 하는 자료가 발생할 경우에 필요로 한다. 이러한 판단은 어떤 상황을 회피하거나, 우선 순위를 두어야 하는 상황에서 사용한다.
  • 활용예시
    • OS에서 프로세스 스케줄링에 우선순위 큐를 활용할 수 있다.
    • 최대 우선순위 큐의 응용분야 중 하나는 공유 컴퓨터에서 작업 순서를 계획하는 것이다. 최대 우선순위 큐는 실행할 작업과 상대 우선순위를 계속 기억하고 있다. 한 작업이 끝나거나 중단될 때, Extract-max를 이용하여 대기중인 작업 중 가장 우선순위가 높은 작업을 선택한다. 새로운 작업은 insert를 사용하여 큐에 새로 들어갈 수 있다.

기본 자료구조

스택과 큐

스택과 큐는 삭제 연산에 의해 집합에서 삭제되는 원소가 미리 제한된 동적집합이다.
(삽입과 삭제의 위치와 방법이 제한된 유한 순서 리스트)

스택

  • 스택 에서는 가장 최근에 삽입된 원소가 삭제된다. 스택은 후입선출(LIFO) 정책을 구현한 것이다.
  • 스택에서 삽입 연산은 Push, 삭제 연산은 Pop이라 불린다.
  • 비어있는 스택에서 원소를 추출하려고 할 때 stack underflow라고 하며, 스택이 넘치는 경우 stack overflow 라고 한다.
  • 활용예시 : 후입선출(LIFO)의 특징을 활용하여 여러 분야에서 활용 가능하다.
    • 웹 브라우저 방문기록 (뒤로가기)
    • 실행취소 (undo)
    • 역순 문자열 만들기
    • 수식의 괄호 검사 (연산자 우선순위 표현을 위한 괄호 검사)
    • 후위표기법 계산

  • 에서는 집합에서 가장 오랜 시간 존재했던 원소를 삭제한다. 큐는 선입선출(FIFO) 정책을 구현한 것이다.
  • 큐에서 삽입 연산은 Enqueue, 삭제연산은 Dequeue라 한다.
  • 스택에서는 원소의 삽입, 삭제가 스택의 한 끝에서 이루어지고, 큐에서는 원소의 삽입, 삭제가 큐의 서로 다른 쪽 끝에서 이루어진다.
  • 양방향 큐 (deque) - 데크 는 원소의 삽입, 삭제가 양쪽 방향에서 이루어진다.
    (큐와 스택을 합친 것으로 선입선출/후입선출의 복합적인 성격이 필요한 경우에 사용)
  • 활용예시 :선입선출(FIFO)의 특징을 활용한 활용예시
    • 우선순위가 같은 작업 예약 (인쇄 대기열)
    • 선입선출이 필요한 대기열 (티켓 카운터)
    • 콜센터 고객 대기시간

해시 테이블

  • 해시 테이블은 사전을 구현하는 가장 효율적인 자료구조이다.
  • 이론적으로는 해시 테이블에서 원소를 찾는 것이 연결 리스트에서 원소를 찾는 것 (O(n)) 만큼 오래 걸릴 수 있지만, 실제 해싱은 성능이 탁월하다.
  • 일반적으로 해시 테이블에서 원소를 찾는 데 걸리는 수행시간은 O(1)이다.
  • 해시 테이블은 단순한 표현인 배열을 일반화 한 것이다.
  • 일반적인 배열에 대한 직접 번지화 방법은 배열의 임의의 위치를 O(1)안에 접근하게 하는 효율적인 방법이다.

170522-0528_TIL

|

5월 28일 (일)

오늘 한 일

  • 알고리즘 문제를 풀었다.
  • Introduction to Algorithms를 훑어보았다. 아직은 내가 읽을 수 있는 책은 아니라는 생각이 들었다. 그래도 중요한 내용 몇가지는 메모해두었다.

내일 할 일

  • 알고리즘 문제 풀기
  • 컴퓨터 공학 강의노트 읽기

5월 27일 (토)

오늘 한 일

내일 할 일

  • 알고리즘 문제 풀기
  • Introduction to Algorithms 추천받은 책인데 내일 친구가 빌려주기로 해서 목차라도 읽어보려고 한다. (무려 1312쪽짜리 책..)
  • OOP 관련 글 읽기
  • 컴퓨터 공학 강의노트 읽기

5월 26일 (금)

오늘 한 일

  • 알고리즘 문제를 풀었다.
  • quick sort 구현을 연습했다. - 기존에 학습한 구현방식위키백과의 python 구현방식이 달랐다. 위키백과의 방법은 파이썬의 특성을 활용해서 의사코드와는 다르게 더 간단하게 구현되어 있었다. 개인적으로는 위키백과의 방식이 더 이해가 잘 가지만 둘 다 잘 이해하고 구현할 수 있도록 해야겠다. (아직은 어렵다..)

5월 25일 (목)

오늘 한 일

  • quick sort 강의를 찾아서 들었다. 분할정복기법(divide and conquer) 을 사용한다는 점에서 merge sort와 유사하다는 인상을 받았다. 하지만 마찬가지로 구현 부분은 더 공부하고 연습 해야겠다고 생각했다. (재귀에 익숙해지자!)
  • google campus seoul 행사에 참여했다. 개발자 분들과 직접 이야기를 나누고 현업에서 중요하게 생각하는 부분들 (문제 해결능력, 학습능력)에 대해서 들을 수 있어서 좋았다.
  • BeautifulSoup 라이브러리를 활용하여 네이버 웹툰 페이지에서 원하는 정보(제목, 링크, 평점, 게시일)를 스크랩핑하는 연습을 했다.

내일 할 일

  • quick sort, merge sort 구현 연습
  • 알고리즘 문제 풀이
  • 객체지향에 대해서 복습하기

5월 24일 (수)

오늘 한 일

  • 처음 시작하는 파이썬 ch6 class관련 연습문제 풀이, ch7 정규표현식 부분을 공부했다.
  • 개인프로젝트 (IT행사 알리미)를 시작했다. 부담없이 재밌게 만들어봐야지
    • 모델 설계 및 구현
  • merge sort 강의를 찾아서 들었는데 구현 부분이 다른 정렬 알고리즘보다 복잡해서 그런지 잘 이해가 가지 않았다. 다시 한번 공부해야겠다.

내일 할 일

  • google campus seoul 행사 참여
  • merge sort 구현 연습, 관련 자료 블로그 정리
  • 개인프로젝트 model class에 summernote 필드적용

5월 23일 (화)

오늘 한 일

  • 객체지향 프로그래밍에 대해서 공부했다.
    • 파이썬의 property (getter), setter
    • 클래스 메소드, 스태틱 메소드 자료
    • 다형성, 은닉화, 추상화
  • 비교를 통해서 이미 정렬된 부분의 중복 비교 부분을 제거하여, bubble sort 성능을 향상시키는 방법에 대해서 공부했다.
  • 처음 시작하는 파이썬 ch6. 객체와 클래스 부분을 읽었다.

내일 할 일


5월 22일 (월)

오늘 한 일

  • 처음 시작하는 파이썬 ch5.모듈,패키지,프로그램 부분을 읽었다. 지난 토요일 알고리즘 문제를 풀면서 itertools 모듈의 강력함을 실감했었다. 파이썬 표준 라이브러리를 잘 활용할 수 있도록 해야겠다.
  • AskDjango 장고 기본강의를 들었다.
    • 커스텀 위젯을 활용하여 네이버 맵 위젯을 적용해보았다.
    • 네이버 지도 API documents를 참고하여 지도를 원하는 형태로 사용해봐야겠다.
  • selection sort, insertion sort, bubble sort 구현연습

내일 할 일

level 2. 2016년

|

문제

2016년 1월 1일은 금요일입니다. 2016년 A월 B일은 무슨 요일일까요? 두 수 A,B를 입력받아 A월 B일이 무슨 요일인지 출력하는 getDayName 함수를 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각

SUN,MON,TUE,WED,THU,FRI,SAT

를 출력해주면 됩니다. 예를 들어 A=5, B=24가 입력된다면 5월 24일은 화요일이므로 TUE를 반환하면 됩니다.

풀이코드

def getDayName(A,B):
    days=["FRI","SAT","SUN","MON","TUE","WED","THU"]
    months=[31,29,31,30,31,30,31,31,30,31,30,31]
    day_total = sum(day_num[:A-1])+B
    return day_list[(day_total % 7)-1]