자격증

[PCCP]프로그래머스 PCCP 자격증 시험 준비 -python

haebogu 2024. 7. 22. 21:43
PCCP를 준비하기 위한 자료구조 및 알고리즘

&& 동일한 결과를 도출하더라도 입력값과 목적에 따라 적합한 자료구조 및 알고리즘을 선택하여 최적의 코드를 작성할 수 있다.&&

1. 회문을 판별하는 방법 : 문자열의 역순과 원 문자열이 동일한지를 확인하는 방법
회문 판별 접근법 1 : 역순의 문자열을 만들고 기존의 문자열과 같은지 확인 / 모든 문자가 일치할 시 True
# 회문 : 문자를 뒤집어도 동일한 문자열. 
# 문자를 뒤집었을 때 같으면 True, 아니면 False를 return 하는 함수
def rev(word):
    rev_word = word[::-1]
    if word == rev_word:
        return True
    else: 
        return False
    # 위 방식은 적어도 n번 이상의 연산이 이루어져아함. 뒤집어서 각각 비교 :O(N+N/2)
    # 그런데 회문은 절반만 확인해도 동일한 것인지를 확인할 수 있다. :O(N/2)  -> 아래 다른 방법
print(rev('abxxba')) # True
print(rev('abccbb')) # False
회문 판별 접근법2 : 문자열의 양 끝 인덱스 값에서 부터 중앙 방향으로 확인 / 일치하지 문자가 있을 시 False
# 회문이 맞는 경우 => 전체에 대해서 같음을 확인해야 한다. 
# 회문이 아닌 경우 => 한번이라도 다르면 아닌것이다. 
def func(word):
    n = len(word)
    left = 0 # index
    right = n-1 # index
    while right > left: # 오른쪽의 인덱스 값이 좌측보다 작거나 같아지면 확인 종료
        if word[left] != word[right]: 
            return False # 동일하지 않은 문자가 발견됨과 동시에 False return
        left += 1 # 문자열을 오른쪽과 왼쪽에서 중간으로 읽어오면서 동일한지 확인
        right -= 1
    return True # 일치하지 않는 값이 없을 때 True return
print(func("AABBBBAA")) # True

 

2. 이차원 리스트를 만드는 여러 방법들 : 이차원 배열을 생성하고 값을 변경하는 원리를 이해
#[[1, 2, 3, 4],
#[5, 6, 7, 8], 
#[9, 10, 11, 12], 
#[13, 14, 15, 16]]
방법1 : 4X4 배열을 생성 후, num의 초기값을 1로 설정하고 반복에 따라 1씩 늘려가며 리스트의 값을 변경. 
n, m = 4, 4
mat = [[0]*n for _ in range(m)]

num = 1 
for i in range(m):
    for j in range(n):
        mat[i][j] = num # 값을 하나씩 수정
        num += 1 # 값의 증가 패턴
print(mat)
방법2: 4X4 배열을 생성 후,각 행의 첫번째 값을 기준으로 변화하는 값의 패턴 파악
mat2 = [[0]*n for _ in range(m)]
for i in range(m):
    for j in range(n):
        mat2[i][j] = 4 * i + j + 1  # 각 행의 [0]값들의 패턴 and 열의 증가 패턴
print(mat2)
방법3: 빈 리스트 생성 후, 각 행의 리스트를 패턴에 따라 생성한 후 빈 리스트에 추가.
mat3 = []
for num in range(4):
    lst = list(range(4*num+1, 4*num+1+4))
    mat3.append(lst)
print(mat3)
방법4: 4X4 배열을 생성 후, 4로 나눈 몫과 나머지로 인덱스와 요소의 값을 표현. 
mat4 = [[0]*n for _ in range(m)]
for num in range(16):
	# 인덱스 값의 증가 패턴 
    i = num // 4 # 0 1 2 3 / 열에서의 변화 : [[0][1][2][3]]
    j = num % 4	# 0 1 2 3 / 행에서의 변화 : [0, 1, 2, 3] 
    mat4[i][j] = num + 1
print(mat4)

 

3. 정렬과 탐색 : 기본적인 정렬과 탐색을 통해 수를 원하는 순서대로 배열되도록 하는 방법
 0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내는 방법! 
def solution(numbers):
    # n_lst = sorted(numbers, reverse=True) 
    n_lst = list(map(str, numbers)) # 9 5 3 과 같이 맨 앞자리의 수를 비교하기 위해 문자로 변화
    n_lst.sort(key=lambda x:x*3, reverse= True) # 서로 다른 자리수임에도 비교를 가능하게 함
    return str(int("".join(n_lst))) # '00'과 같이 수의 형태가 아닌 것을 처리하기 위함
    
numbers = [3, 30, 34, 5, 9]
solution(numbers) 
# output : "9534330"

 

4. 그리디 알고리즘: 각 단계 기준 최적을 선택 하고, 조건을 만족시키 않으면 선택 항목을 제외하고 다시 선택
 (백준) 설탕배달 문제 : Nkg의 설탕을 5kg과 3kg 단위로 최소한의 개수가 되도록 묶는 방법

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

N = int(input())
cnt = N//5
answer = 0
while cnt >= 0:
    # print("cnt:", cnt)
    if N == 5*cnt + 3*((N-5*cnt)//3):
        answer = cnt + ((N-5*cnt)//3)
        break
    else: 
        cnt -= 1
else: answer = -1
print(answer)

# 방법1 : 일단 5로 나눠보고, 5의 개수를 하나씩 줄여가며 3으로 나눈다. 

N = int(input())
def sugar(N):
    cnt = 0
    for i in range(0,4+1): # 3의 최대 개수는 5개이다. / 3과 5의 최소공배수 = 15
        new = N-3*i # 5의 개수가 가장 많은 것이 최적 
        if new >= 0 and new%5==0: # 조건에 맞지 않을 경우 3을 늘려가며 반복
            cnt = i + new//5
            # print(i, new//5)
            return cnt
    else: 
        return -1
print(sugar(N))

# 방법2: 일단 5로 나눠보고, 3의 개수를 하나씩 늘려가며 5로 나눈다. 

 

5. 피보나치 수열을 푸는 여러가지 방법들 : Fibo(n) = Fibo(n-1)+Fibo(n-2)

https://school.programmers.co.kr/learn/courses/30/lessons/12945 (프로그래머스 피보나치 수)

def solution(n):
    F_lst = [0]*(n+1)
    F_lst[0], F_lst[1] = 0, 1
    for i in range(2, n+1):
        F_lst[i] = F_lst[i-1]+F_lst[i-2]
    return F_lst[-1]

# 방법1: N+1 크기의 리스트를 만들고, 0부터 N까지 피보나치 수를 하나씩 저장해 가는 방식: (Down-Top) 메모라이제이션

def solution(n):
    a, b = 0, 1
    for _ in range(2, n//2+1+1):
        a, b = (a+b), (a+b+b)
    return (a if n%2==0 else b)

# 방법2: 2개씩 쌍으로 하여 값을 갱신해가며 N 까지의 값을 도출해가는 방식 : 동적 프로그래밍

def F(n):
    if n == 0 : return 0
    if n == 1 : return 1
	return F(n-1)+F(n-2)
    
def solution(n):
    return F(n)

# 방법3: 재귀함수를 사용하여 값을 구하는 방식 : (Top-Dowm) 재귀함수

def F(n, memo = {}):
    if n in memo: return memo[n]
    if n == 0 : return 0
    if n == 1 : return 1
    memo[n] = F(n-1, memo)+F(n-2, memo)
    return memo[n]
    
def solution(n):
    return F(n)

# 방법4: 재귀함수에서 값을 저장하며 구해가는 방식: (Top-Down) 재귀함수 + 메모라이제이션