Why Pythonic code?

남 코드에 대한 이해도 : 많은 개발자들이 python 스타일로 코딩한다.

효율 : 단순 for loop append 보다 list가 조금 더 빠르다. 익숙해지면 코드가 짧아진다.

 

Split

type의 값을 "기준값"으로 나눠서 List 형태로 변환

a = "   EXTRA   SPACE   "

b = a.split().lower()
c = a.split(' ')

print(b)    # ['EXTRA', 'SPACE']
print(c)    # ['', '', '', 'EXTRA', '', '', 'SPACE', '', '', '']

 

list comprehension

  • 기존 List 사용하여 간단히 다른 List를 만드는 기법
  • 다른 List를 포함해서 새로운 List를 만드는 것.
  • 파이썬에서 가장 많이 사용되는 기법 중 하나
  • 일반적으로 for + append 보다 속도가 빠름
result = []
for i in range(10):
	result.append(i)
	# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

result = [i for i in range(10)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
result = [i for i in range(10) if i % 2 == 0]
# [0, 2, 4, 6, 8]
result = [i if i % 2 == 0 else -1 for i in range(10)]
# [0, -1, 2, -1, 4, -1, 6, -1, 8, -1]

word_1 = "Hello"
word_2 = "World"
result = [i + j for i in word_1 for j in word_2]
# ['HW', 'Ho', 'Hr', 'Hl', 'Hd', 'eW', 'eo', 'er', 'el', 'ed', 'lW', 'lo', 'lr', 'll', 'ld', 'lW', 'lo', 'lr', 'll', 'ld', 'oW', 'oo', 'or', 'ol', 'od']

case_1 = ["a","b","c"]
case_2 = ["d","e","a"]
result = [i+j for i in case_1 for j in case_2] # case_1부터
# ['ad', 'ae', 'aa', 'bd', 'be', 'ba', 'cd', 'ce', 'ca']
result = [[i+j for i in case_1] for j in case_2] # case_2부터
# [['ad', 'bd', 'cd'], ['ae', 'be', 'ce'], ['aa', 'ba', 'ca']]
result = []
for i in range(10):
	result.append(i)
	# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

result = [i for i in range(10)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
result = [i for i in range(10) if i % 2 == 0]
# [0, 2, 4, 6, 8]
result = [i if i % 2 == 0 else -1 for i in range(10)]
# [0, -1, 2, -1, 4, -1, 6, -1, 8, -1]

word_1 = "Hello"
word_2 = "World"
result = [i + j for i in word_1 for j in word_2]
# ['HW', 'Ho', 'Hr', 'Hl', 'Hd', 'eW', 'eo', 'er', 'el', 'ed', 'lW', 'lo', 'lr', 'll', 'ld', 'lW', 'lo', 'lr', 'll', 'ld', 'oW', 'oo', 'or', 'ol', 'od']

case_1 = ["a","b","c"]
case_2 = ["d","e","a"]
result = [i+j for i in case_1 for j in case_2] # case_1부터
# ['ad', 'ae', 'aa', 'bd', 'be', 'ba', 'cd', 'ce', 'ca']
result = [[i+j for i in case_1] for j in case_2] # case_2부터
# [['ad', 'bd', 'cd'], ['ae', 'be', 'ce'], ['aa', 'ba', 'ca']]

여담으로 pprint.pprint를 쓰면 이쁘게 나온다!

 

enumerate & zip

enumerate : list의 element를 추출할 때 번호를 붙여서 추출

  • 나오는 형태는 Tuple
for i, v in enumerate('abc'):
	print("{0}  {1}".format(i,v))
	# 0  a
	# 1  b
	# 2  c

for i, v in enumerate(['a','b','c']):
	print("{0}  {1}".format(i,v))
	# 0  a
	# 1  b
	# 2  c

zip : 두 개의 list의 값을 병렬적으로 추출함

alist = ['a1','a2','a3']
blist = ['b1','b2','b3']

[[a,b] for a, b in zip(alist, blist)]
# [['a1', 'b1'], ['a2', 'b2'], ['a3', 'b3']]
[c for c in zip(alist, blist)]
# [c for c in zip(alist, blist)]

list(enumerate(zip(alist, blist)))
# [(0, ('a1', 'b1')), (1, ('a2', 'b2')), (2, ('a3', 'b3'))]

 

lambda & map & reduce

lambda

함수 이름 없이, 함수처럼 쓸 수 있는 익명함수

수학의 람다 대수에서 유래함

def f(x, y):
	return x + y

f = lambda x, y : x + y

PEP 8에서는 lambda의 사용을 권장하지 않음

  • 어려운 문법
  • 테스트의 어려움
  • 문서화 docstring 지원 미비
  • 코드 해석의 어려움
  • 이름이 존재하지 않는 함수의 출현
  • 그래도 쓰는..

Map

두 개 이상의 list에도 적용 가능함, if filter도 사용가능

굳이 map을 사용하기 보다는 list comprehension을 사용하도록

ex = [1,2,3,4,5]
f = lambda x: x ** 2

list(map(f, ex))
# [1, 4, 9, 16, 25]
[f(value) for value in ex]

 

reduce

map function과 달리 list에 똑같은 함수를 적용해서 통합

대용량 데이터를 핸들링할 때, 주로 사용.

from functools import reduce

ex = [1,2,3,4,5]
f = lambda x, y: x + y

print(reduce(f,ex))
# 15

 

generator

Iterable data

  • Sequence형 자료형에서 데이터를 순서대로 추출하는 object
  • 내용이 아닌 위치정보(주소값)에 대한 정보가 저장됨.
  • next를 하면 다음 메모리 주소에 있는 값을 불러옴.
  • cities_주소 → seoul_주소 → busan_주소 → jeju_주소 → 없으므로 에러
cities = ["seoul", "busan", "jeju"]

memory_address = iter(cities)
# <list_iterator at 0x1ec8cbc6788>
next(memory_address) # seoul
next(memory_address) # busan
next(memory_address) # jeju

generator

  • iterable object를 특수한 형태로 사용해주는 함수
  • element가 사용되는 시점에 값을 메모리에 반환
  • yield를 사용해 한번에 하나의 element만 반환함.
  • 용량을 줄일 수 있기 때문에 대용량인 경우 사용하는 것이 효율적임.
import sys

def general_list(value):
	result = []
	for i in range(value):
		result.append(i)
	return result

result = general_list(50)
sys.getsizeof(result)
# 528
import sys

def generator_list(value):
	result = []
	for i in range(value):
		yield i

result = generator_list(50)
sys.getsizeof(result)
# 120
sys.getsizeof(list(generator_list(50)
# 472

When generator

  • list 타입의 데이터를 반환해주는 함수는 generator로!

→ 특히 사용하면 읽기 쉽고, 중간 과정에서 loop가 중단될 수 있을때

  • 큰 데이터를 처리할 때는 generator expression을 고려

→ 데이터가 커도 처리의 어려움이 없음.

  • 파일 데이터를 처리할 때도 generator를 사용하자

 

asterisk

함수에 입력되는 parameter의 변수명을 사용하여 argument를 넘김.

# Keyword arguments
def print_name_keyword(name, you_name):
	print("Hello {}, my name is {}".format(you_name, name))

print_name_keyword(name="aaa",you_name="bbb")

# default arguments
def print_name_default(name, you_name="NAVER"):
	print("Hello {}, my name is {}".format(you_name, name))

print_name_default("hwan")
# Hello NAVER, my name is hwan
print_name_default("hwan", "AA")
# Hello AA, my name is hwan

가변인자(variable-length)

  • 개수가 정해지지 않은 변수를 함수의 parameter로 사용하는 법
  • Keyword arguments와 함계, argument 추가가 가능
  • Asterisk(*) 기호를 사용하여 함수의 parameter를 표시함
  • 입력된 값은 tuple type으로 사용할 수 있음
  • 가변인자는 오직 한 개만 맨 마지막 parameter 위치에 사용가능
def asterisk_test(a, b, *args):
	print(a)
	print(b)
	print(args)
	print(type(args))

asterisk_test(1,2,3,4,5)
# 1
# 2
# (3, 4, 5)
# <class 'tuple'>

키워드 가변인자(Keyword variable-length)

  • Parameter 이름을 따로 지정하지 않고 입력하는 방법
  • asterisk(*) 두개를 사용하여 함수의 parameter를 표시함
  • 입력된 값은 dict type으로 사용할 수 있음
  • 가변인자는 오직 한 개만 기존 가변인자 다음에 사용
def kwargs_test(**kwargs):
	print(kwargs)
	print(type(kwargs))

kwargs_test(first=3, second=4, third=5)
# {'first': 3, 'second': 4, 'third': 5}
# <class 'dict'>

결론으로는 argument는 그냥 파라미터, 키워드 파라미터, 가변인자, 키워드 가변인자 순으로 작성해야함.

def test_3(one, two=3, *args, **kwargs):
	print(one,two, args, kwargs)

test_3(1,2,3,4,5,6,6,a=100,b=200)
# 1 2 (3, 4, 5, 6, 6) {'a': 100, 'b': 200}

 

asterisk(*)

  • 흔히 알고 있는 *를 의미함.
  • tuple, dict 등 자료형에 들어가 있는 값을 unpacking
  • 함수의 입력값, zip 등에 유용하게 사용가능
def asterisk_test(a, *args):
	print(a, args)
	print(type(args))

def asterisk_test2(a, args):
	print(a, *args)
	print(type(args))

asterisk_test(1,*(2,3,4,5,6)) # (1,2,3,4,5,6)과 같음
# 1 (2, 3, 4, 5, 6)
# <class 'tuple'>
asterisk_test(1,(2,3,4,5,6))
# 1 2 3 4 5 6
# <class 'tuple'>

data = ([1,2,],[3,4,],[5,6,])
print(*data)
# [1, 2] [3, 4] [5, 6]
for i in zip(*data):
    print(i)
# (1, 3, 5)
# (2, 4, 6)

def asterisk_test(a,b,c,d):
    print(a,b,c,d)
    
data = {"b":1,"c":2,"d":3}
asterisk_test(10, **data)
# 10 1 2 3

문제 리뷰

  1. DFS와 BFS를 매트릭스를 통해 구현되는 방식이다.
  2. DFS와 BFS의 정석으로 기초인 문제같다.

문제 링크

 

1260번: DFS와 BFS

첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사

www.acmicpc.net


import sys
from collections import deque

n, m, v = map(int, sys.stdin.readline().split())
matrix = [[0] * (n+1) for _ in range(n+1)]

for _ in range(m):
    # 입력값 매트릭스로 구현
    line = list(map(int,sys.stdin.readline().split()))
    matrix[line[0]][line[1]] = 1
    matrix[line[1]][line[0]] = 1

# DFS 구현
def dfs(start, visited):
    # stack 활용
    visited += [start]
    for c in range(len(matrix[start])):
        # start에서 c로 갈 수 있으면서 아직 방문하지 않은 경우에 방문.
        if matrix[start][c] == 1 and c not in visited:
            dfs(c,visited)
    return visited

# BFS 구현
def bfs(start):
    # Queue로 구현
    visited = [start]
    queue = deque([start])

    while queue:
        # popleft로 0에 값 뽑기
        n = queue.popleft()
        for c in range(len(matrix[start])):
            # n에서 c로 갈 수 있으면서 아직 방문하지 않은 경우에 방문.
            if matrix[n][c] == 1 and c not in visited:

                visited.append(c)   # 방문처리
                queue.append(c)     # Queue에 추가
    return visited

'백준' 카테고리의 다른 글

[백준] 지구 온난화 -Python  (0) 2021.02.18
[백준] N-Queen -Python  (0) 2021.01.24
[백준] 줄 세우기 -Python  (0) 2021.01.18
[백준] 가장 긴 바이토닉 부분 수열 -Python  (0) 2021.01.18
[백준] RGB거리 -Python  (0) 2021.01.14

Python의 시작

  • 1991년 귀도 반 로섬이 발표한 언어
  • 플랫폼 독립적
  • 인터프리터 언어
  • 객체 지향 언어
  • 동적 타이핑 언어
  • 처음 C언어로 구현됨

 

이름의 유래

귀도 반 로섬이 Monpy Python's Flying circus라는 코미디프로를 좋아하여 해당 프로그램에서 이름을 따서 Python이라고 지었다고 합니다.

혹은 그리스 신화 속에서 델포이 신탁소를 지키던 뱀인 피톤에서 유래했다고도 합니다. 정확한 것은 아니지만 이러한 이유 때문에 아나콘다라는 이름이 나왔다고 생각(?)할 수 있습니다ㅎㅎ

 

Python의 특징

플랫폼 독립적인 인터프리터 언어

  • 플랫폼(OS) : 윈도우, 리눅스, 안드로이드, Mac os, ios 등 프로그램이 실행하는 운영체제를 플랫폼이라고 합니다.
  • 독립적인(관계없는, 상관없는) : OS에 상관없이 한번 프로그램을 작성하면 사용가능.
  • 인터프리터(통역기를 사용하는 언어) : 소스코드를 바로 실행할 수 있게 지원하는 프로그램 실행 방법.

결론적으로 파이썬은 파이썬 문법에 따라서 적으면 되지만 운영체제에서 작동을 하기 위해선 각각의 운영체제에 맞는 인터프리터 프로그램을 설치해서 번역해주는, 해석해주는 것이라고 생각하면 됩니다.

 

컴파일러와 인터프리터 언어의 차이점

  컴파일러 인터프리터
작동방법 소스코드를 기계어로 먼저 번역
해당 플랫폼에 최적화되어 프로그램을 실행
별도의 번역과정 없이 소스코드를 실행한 시점에 해석하여 컴퓨터가 처리할 수 있도록 함.
장점
단점
실행속도가 빠름
한 번의 많은 기억 장소 필요
간단히 작성, 메모리가 적게 필요
실행속도가 느림
주요 언어 C, C++, C#, Java 파이썬, 스칼라

 

객체 지향 언어

실행 순서가 아니라 단위 모듈(객체) 중심으로 프로그램을 작성합니다.

하나의 객체는 어떤 목적을 달성하기 위한 행동(method)와 속성(attribute)을 가지고 있습니다.

 

객체 지향 특징

  1. 캡슐화(Encapsulation)
    • 데이터(속성)와 데이터를 처리하는 함수를 하나로 묶는 것.
    • 캡슐화된 객체의 세부 내용이 외부에 은폐(정보 은닉)되어, 변경이 발생할 때 오류의 파급효과가 낮아짐.
    • 재사용 용이
  2. 정보은닉(Information Hiding)
    • 캡슐화에서 가장 중요
    • 다른 객체에게 자신의 정보를 숨기고 자신의 연산만을 통하여 접근 허용.
  3. 추상화(Abstractions)
    • 불필요한 부분을 생략하고 객체의 속성 중 가장 중요한 것에만 중점을 두어 개략화한 것.
    • 모델화 하는 것.
  4. 상속성(Inheritance)
    • 이미 정의된 상위 클래스(부모 클래스)의 모든 속성과 연산을 하위 클래스가 물려 받는 것.
    • 상속성을 이용하면 하위 클래스는 상위 클래스의 모든 속성과 연산을 자신의 클래스 내에서 다시 정의하지 않고서도 즉시 자신의 속성으로 사용가능.
  5. 다형성(Polymorphism)
    • 메시지에 의해 개체(클래스)가 연산을 수행하게 될 때 하나의 메시지에 대해 각 객체(클래스)가 가지고 있는 고유한 방법(특성)으로 응답할 수 있는 능력을 의미.
    • 객체(클래스)들은 동일한 메소드명을 사용하며 같은 의미의 응답을 함.

동적 타이핑 언어

프로그램이 실행하는 시점에 프로그램이 사용해야할 데이터에 대한 타입을 결정합니다.

간단하게 프로그램이 실행하는 시점이란 것이 동적이라는 것으로 생각하면 됩니다.

 

Why Python?!

  • 쉽고 간단하며 다양합니다.
  • 이해하기 쉬운 문법 -> 사람의 시간이 줄어든다.(사람의 시간이 기계의 시간보다 중요함)
  • 다양한 라이브러리 : 파이썬 대부분의 라이브러리가 다른 사용자에 의해서 구현되어 있습니다.

처음 들었지만 너무나 맘에 들었던 말로 마무리하겠습니다.😀

Life is short. You need Python!

글을 시작하며

해당 카테고리는 네이버 부스트캠프의 교육일지로 작성하는 페이지입니다.

강의를 기반으로 작성하며, 추가적으로 필요한 부분은 책과 구글링을 통해서 추가했습니다. 😀

 

Operating System(운영체제)

  • 우리의 프로그램이 동작할 수 있는 구동 환경입니다.
  • 프로그램은 운영체제에 따라서 방식이 다릅니다. 예를 들면 윈도우에서는 exe 실행파일로 프로그램이 실행되지만 Mac에서는 실행되지 않습니다.
  • 어떤 개발 환경에서 개발을 실행할 것인가에 대한 선택을 해야합니다.

File System(파일 시스템)

OS에서 파일을 저장하는 트리구조 저장 체계로 파일의 기본체계에는 파일과 디렉토리가 있습니다.

디렉터리(Directory) 파일(File)
폴더 또는 디렉터리라 불림. 컴퓨터에서 정보를 저장하는 논리적인 단위(위키피디아 참고)
파일과 다른 디렉터리를 포함할 수 있음. 파일은 파일명과 확장자로 구분(ex : hello.py)
실행, 쓰기, 읽기 등을 할 수 있음.

파일의 고유한 위치를 경로라고 합니다. 트리구조상 노드의 연결입니다. 경로에는 절대 경로와 상대 경로가 있습니다.

 

절대 경로

  • 루트 디렉터리부터 파일 위치까지의 경로
  • ex : C:\user\docs\test.txt

상대 경로

  • 현재 있는 디렉터리부터 타깃 파일까지의 경로
  • ../../test.txt

 

CLI(Command Line Interface)

GUI(Graphic User Interface)와 달리 Text를 사용하여 컴퓨터에 명령을 입력하는 인터페이스 체계

 

Windows - CMD, Windows Terminal, cmder

Mac, Linux - Terminal

 

MS Store에서 Unbuntu도 지원하고 있어서 Linux Terminal을 사용할 수 있습니다.

 

기본적인 Shell 명령어

윈도우 CMD 창 명령어 Shell 명령어 설명
CD cd 현재 디렉토리 이름을 보여주거나 바꿉니다. (change directory)
CLS clear CMD 화면에 표시된 것을 모두 지웁니다.(clear screen)
COPY cp 하나 이상의 파일을 다른 위치로 복사
DEL rm 하나 이상의 파일을 지움(delete)
DIR ls 디렉토리에 있는 파일과 하위 디렉터리 목록을 보여줌.(directory)

 

문제 후기

  1. 이전에 프로그래머스에서 푼 순위라는 문제와 비슷하다고 생각했습니다. 아래에 링크를 남기겠습니다.
  2. 순위에서 푼 방식대로 모든 사람의 해쉬를 만들고 비교한 값을 통해 갱신하는 방식으로 하니 메모리 초과로 틀렸고 알고리즘을 변경하기로 했습니다.
  3. 알고리즘을 생각하다 DFS로 생각했고 문제를 풀었습니다.
  4. DFS외에, 위상정렬이라는 것이 있는 것을 알게 됐고 모르는 방식이라 공부를 했습니다. terms.naver.com/entry.nhn?docId=3579618&cid=59086&categoryId=59093를 보고 위상정렬이 어떤 것인지 파악했습니다.
  5. 위상 정렬 알고리즘으로 비교에서 큰 적이 없는 값부터 시작해서 DFS 방식으로 하나씩 차례대로 나아가는 방식으로 해결했습니다.
 

위상 정렬 알고리즘

우리가 일상생활에서 하는 모든 행동은 순서가 정해져있다. 외출을 하려고 신발을 신기 위해선 먼저 양말 먼저 신어야 한다. 신발부터 신고 양말을 신을 수는 없다. 라면, 떡볶이 등 음식을 만들

terms.naver.com

 

 

[프로그래머스] 순위 -Python

문제후기 문제에서 n이 1이상 100이하인 것과 경기 결과가 1개 이상 4,500개 이하인 것을 보고 완전탐색이 가능하다고 판단했습니다. 입출력 예시에서처럼 5번 선수는 다른 선수와 경기를 하지 않

hwanii-with.tistory.com

문제링크

 

2252번: 줄 세우기

첫째 줄에 N(1≤N≤32,000), M(1≤M≤100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의미이

www.acmicpc.net


from sys import stdin
from _collections import deque

N, M = map(int, stdin.readline().split())

num_dict = {}

for n in range(1,N+1):
    num_dict[n] = []


taller = [0] * (N+1)    # 큰 횟수
queue = deque([])       # 큐 생성


for _ in range(M):
    A, B = map(int, stdin.readline().split())
    # B에 큰 횟수를 저장
    taller[B] += 1
    # A에서 B로 갈 수 있도록 설정(DFS)
    num_dict[A].append(B)

# 비교에서 큰 적이 없는 값
for num in range(1,N+1):
    if taller[num] == 0:
        queue.append(num)
# 결과값
answer = []

# queue에 값이 있는 동안 반복
while queue:
    now = queue.popleft()
    # 결과값에 추가
    answer.append(str(now))

    # 간선 파악
    for i in num_dict[now]:
        # 1이면 queue에 추가
        if taller[i] == 1:
            queue.append(i)
        taller[i] -= 1
print(" ".join(answer))

'백준' 카테고리의 다른 글

[백준] N-Queen -Python  (0) 2021.01.24
[백준] DFS와 BFS -Python  (0) 2021.01.20
[백준] 가장 긴 바이토닉 부분 수열 -Python  (0) 2021.01.18
[백준] RGB거리 -Python  (0) 2021.01.14
[백준] 욕심쟁이 판다 -Python  (0) 2021.01.12

문제 후기

  1. 문제를 보고 이전에 프로그래머스에서 풀어본 풍선 터뜨리기와 비슷한 문제라고 생각을 했습니다. 아래에 링크를 남기겠습니다.
  2. 풍선 터뜨리기 처럼 가장 큰 값을 이용해서 풀려고 했으나 반례가 있어서 다른 방법으로 풀어야했습니다.
  3. 최악의 경우를 고려해봤을때 단순히 모든 배열을 탐색해도 된다 판단하여 모든 배열을 기준으로 찾기로 했습니다.
  4. 각 인덱스 값을 기준으로 왼쪽부분과 오른쪽부분으로 나눠 스택과 이분탐색을 활용하여 스택을 만들었습니다.
  5. 문제의 예시를 들면, 1 5 2 1 4 3 4 5 2 1이고 굵은 5가 기준이면 왼쪽 배열은 아래와 같은 순서로 이뤄집니다.
    1. [1]   비어있는 배열에 1 추가
    2. [1,2]   스택의 맨 위의 값 1보다 크므로 스택에 2 추가
    3. [1,2]   스택의 맨 위의 값 2보다 작으므로 이분탐색하여 1->1 교체 (이분탐색하면 idx가 0)
    4. [1,2,4] 스택의 맨 위의 값 2보다 크므로 스택에 4 추가
    5. [1,2,3] 스택의 맨 위의 값 4보다 작으므로 이분탐색하여 4->3 교체 (이분탐색하면 idx가 2)
    6. [1,2,3,4] 스택의 맨 위의 값 3보다 크므로 스택에 4 추가

 

 

[프로그래머스] 풍선 터뜨리기 -Python

문제 후기 비슷한 문제를 이전 카카오 코테에서도 효율성으로 인해서 풀지 못한 기억이 있었다. 이번 문제 역시 제한사항으로 백만이 주어지는 것을 보고 단순 완전탐색으로 할 경우 효율성에

hwanii-with.tistory.com

문제링크

 

11054번: 가장 긴 바이토닉 부분 수열

첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

www.acmicpc.net


from sys import stdin
from bisect import bisect_left

N = int(stdin.readline())

arr = list(map(int, stdin.readline().split()))

# 만약 배열 크기가 1이면 1출력하고 종료
if len(arr) == 1:
    print("1")
else:

    answer = 0  # 결과값
    # 모든 인덱스 탐색
    for idx in range(len(arr)):
        # 왼쪽 부분과 오른쪽 부분 나눠서 실행
        # 값 부분은 stack으로 숫자 입력
        left_stack, right_stack = [], []
        
        # 왼쪽 부분
        for i in range(idx):
            # 해당값보다 큰 경우 넘어가기
            if arr[i] >= arr[idx]:
                continue
            # 첫번째 값.
            elif left_stack == []:
                left_stack.append(arr[i])
            else:
                # 만약 stack 마지막 값보다 큰 경우는 추가
                if left_stack[-1] < arr[i]:
                    left_stack.append(arr[i])
                # 만약 stack 마지막 값보다 작은 경우
                # 이분 탐색으로 해당 값이 들어갈 위치 찾아서 교체
                else:
                    left_stack[bisect_left(left_stack, arr[i])] = arr[i]

        # 오른쪽 부분
        for i in range(len(arr) - 1, idx,-1):
            # 해당값보다 큰 경우 넘어가기
            if arr[i] >= arr[idx]:
                continue
            # 첫번째 값
            elif right_stack == []:
                right_stack.append(arr[i])
            else:
                # 만약 stack 마지막 값보다 큰 경우는 추가
                if right_stack[-1] < arr[i]:
                    right_stack.append(arr[i])
                # 만약 stack 마지막 값보다 작은 경우
                # 이분 탐색으로 해당 값이 들어갈 위치 찾아서 교체
                else:
                    right_stack[bisect_left(right_stack, arr[i])] = arr[i]

        # 만약 오른쪽 부분이 있는 경우 해당값 추가
        if right_stack:
            right_stack.append(arr[idx])
        # 없는 경우에는 왼쪽 부분에 해당값 추가
        else:
            left_stack.append(arr[idx])
        # answer와 왼쪽, 오른쪽 배열 갯수 비교하여 큰 값 저장
        answer = max(answer, len(left_stack) + len(right_stack))

    print(answer)

'백준' 카테고리의 다른 글

[백준] DFS와 BFS -Python  (0) 2021.01.20
[백준] 줄 세우기 -Python  (0) 2021.01.18
[백준] RGB거리 -Python  (0) 2021.01.14
[백준] 욕심쟁이 판다 -Python  (0) 2021.01.12
[백준] 절대값 힙 -Python  (0) 2021.01.10

문제후기

  1. 문제를 보고 이해하는데 오래걸렸습니다. 문제는 R, G, B 값이 하나씩 주어지는데 이때 앞뒤의 집과 달라야한다는 것과 R, G, B를 그리는데 사용되는 페인트의 양이 최소가 되도록 하는 것입니다. 문제를 보고 DP를 보고 풀면 되겠다고 생각했고 이전에 프로그래머스에서 푼 땅따먹기와 같다고 판단했습니다.
  2. R, G, B값과 이전까지 더해진 값의 합을 다시 저장합니다. 이때 이전 위치와 같은 경우는 제외합니다.
  3. 마지막 줄에서 가장 최소의 값을 찾습니다.

예시 풀이

문제 예시를 DP를 이용하면 최종적으로 아래의 값이 나온다.

26 40 83
89(40+49) 86(26+60) 83(57+26)
96(13+83) 172(89+83) 185(99+86)

 

 

프로그래머스에서 비슷한 문제

 

코딩테스트 연습 - 땅따먹기

땅따먹기 게임을 하려고 합니다. 땅따먹기 게임의 땅(land)은 총 N행 4열로 이루어져 있고, 모든 칸에는 점수가 쓰여 있습니다. 1행부터 땅을 밟으며 한 행씩 내려올 때, 각 행의 4칸 중 한 칸만 밟

programmers.co.kr

문제링크

 

1149번: RGB거리

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나

www.acmicpc.net


from sys import stdin

# N 개의 줄
N = int(stdin.readline())

# 배열 RGB값 n개
arr = [list(map(int, stdin.readline().split())) for _ in range(N)]

# 초기 설정값
answer = 1e9

# 1번쨰 줄부터 시작
for n in range(1,N):
    for i in range(3):
        # 미니멈 초기값
        minimum = 1e9
        for j in range(3):
            # 이전과 같은 색인 경우 제외
            # 가장 작은 값 찾기
            if i != j and arr[n][i] + arr[n-1][j] < minimum:
                minimum = arr[n][i] + arr[n-1][j]
        # 가장 작은 값 기록
        arr[n][i] = minimum

print(min(arr[-1]))

문제후기

  1. 처음 문제를 보고 BFS를 활용해서 문제를 풀려고 했습니다. 최악의 경우 500 * 500을 BFS로 탐색하는 경우이지만 시간제한이 2초로 애매하지만 통과할 수 있다고 생각하고 코드를 작성했습니다.
  2. BFS로 제출한 결과 시간초과에서 걸려서 알고리즘이 틀린 것으로 생각하고 알고리즘을 변경했습니다.
  3. 다시 생각해낸 알고리즘은 DP로 최대 Heap과 연관시켜 생각했습니다. 대나무가 많은 순서로 Heap 정렬을 해준 이후 pop을 하면서 메모이제이션을 했습니다. 상하좌우의 메모 중 가장 큰 값 + 1로 메모를 갱신했습니다.
  4. Heap에 남은 값이 없으면 모든 메모가 끝났으므로 메모 중에서 가장 큰 값을 출력했습니다.

문제링크

 

1937번: 욕심쟁이 판다

n*n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에서

www.acmicpc.net


from sys import stdin
import heapq
from itertools import chain

# 상하좌우
dy = [-1,0,1,0]
dx = [0,-1,0,1]

# n 개 매트릭스
n = int(stdin.readline())
# 매트릭스 값 입력
matrix = [list(map(int, stdin.readline().split())) for _ in range(n)]
# 메모이제이션
memoization = [[0] * n for _ in range(n)]
# 최대 힙정렬 할 배열
heap = []

# 최대 힙 정렬
for y in range(n):
    for x in range(n):
        # heapq는 최소힙정렬이므로 -1을 곱해서 최대힙정렬로 한다.
        heapq.heappush(heap, (-1 * matrix[y][x], y, x))


# heap에 값이 없을때까지
while heap:
    _, y, x = heapq.heappop(heap)
    chk_arr = []
    # 상하좌우 체크
    for i in range(4):
        ny = y + dy[i]
        nx = x + dx[i]
        if 0 <= ny < n and 0 <= nx < n:
            # 만약 상,하,좌,우 값이 더 크다면 해당 메모값 배열에 추가
            if matrix[y][x] < matrix[ny][nx]:
                chk_arr.append(memoization[ny][nx])

    if chk_arr: # 만약 배열에 값이 있으면 가장 큰 값 + 1
        memoization[y][x] = max(chk_arr) + 1
    else: # 배열에 값이 없으면 1
        memoization[y][x] = 1
# 메모 중에서 가장 큰 값 출력
print(max(chain(*memoization)))

'백준' 카테고리의 다른 글

[백준] 가장 긴 바이토닉 부분 수열 -Python  (0) 2021.01.18
[백준] RGB거리 -Python  (0) 2021.01.14
[백준] 절대값 힙 -Python  (0) 2021.01.10
[백준] 미확인 도착지 -Python  (0) 2021.01.09
[백준] K번째 수 -Python  (0) 2021.01.08

+ Recent posts