Sad Puppy 3 '코딩테스트' 카테고리의 글 목록 (4 Page) :: 개발자 아지트

https://school.programmers.co.kr/learn/courses/30/lessons/87390

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

정수 n, left, right가 주어집니다. 다음 과정을 거쳐서 1차원 배열을 만들고자 합니다.

 

n n열 크기의 비어있는 2차원 배열을 만듭니다.

i = 1, 2, 3, ..., n에 대해서, 다음 과정을 반복합니다.

1 1열부터 i i열까지의 영역 내의 모든 빈 칸을 숫자 i로 채웁니다.

1, 2, ..., n행을 잘라내어 모두 이어붙인 새로운 1차원 배열을 만듭니다.

새로운 1차원 배열을 arr이라 할 때, arr[left], arr[left+1], ..., arr[right]만 남기고 나머지는 지웁니다.

정수 n, left, right가 매개변수로 주어집니다. 주어진 과정대로 만들어진 1차원 배열을 return 하도록 solution 함수를 완성해주세요.

 

 

문제 해결 방법

 

2차원 배열 특정 위치에 해당되는 첨자 같은 공식이라고 있었다. 

 

행첨자는 ([현 위치]) / (전체 열의 수 )

열 첨자는 ([현 위치]) % (전체 열의 수)  

 

이거랑 코드 구현의 아이디어랑 관련이 있다. 

 

왜냐하면 문제의 제한사항을 감안하고 구현하려면 left부터 right 까지의 값을 가진 배열을 바로 구해야(left이전의 값이나 right이후의 값을 계산하면 시간초과 이슈 발생)한다. 

 

해당 배열을 바로 구하기 위해서는 문제에서 제공한 행과 열에 대한 값의 관계를 생각해서 행첨자와 열첨자를 이용해 문제를 풀어야만 한다. 

 

행과 열 첨자를 구하면 두 값중 큰 값이 해당 위치의 원소의 값이 된다. 

 

코드 구현

 

def solution(n, left, right):
    answer = []
    for i in range(left,right+1):
        
        a = (i // n) +1# 몫 행첨자 
        b = (i % n) +1#나머지  열 첨자 
        print('a', a, 'b', b)
        if a < b :
            print('check')
            a, b = b, a
        answer.append(a)

    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 / 어려웠던 점

 

진짜 굉장히 어렵다고 생각하는 문제다.

 

처음에 2중 반복문으로 풀었는데 테스트케이스 대부분 시간초과 났따. 그래서 반복문을 하나로 줄였는데도 비슷했다. 

 

굉장히 어렵다고 생각한다. 내가 뭘 모르는건가?

 

그래서 진짜 끙끙 앓다가 힌트랑 남의 코드 봤다. 보고도 이해가 안갔다. 진짜 내가 뭘 모르는게 분명하다. 

 

찾아보니 2차원 배열 특정 위치에 해당되는 첨자 같은 공식을 참고해서 풀었다. 

 

확실히 나는 해당 개념을 몰랐다. 그래서 문제 풀때도 아이디어를 거의 없는걸 창조해서 풀듯이 했고, 남의 코드를 봐도 

 

이해를 잘 못했던 것 같다. 

 

글로 쓰고나니 별거아닌거 같은 이 느낌은 뭐지 ;;; 휴,, 거진 서너시간은 날린 것 같다. 

 

그래도 좋은 경험이였다. 

 

https://school.programmers.co.kr/learn/courses/30/lessons/131701#qna

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

 

철호는 수열을 가지고 놀기 좋아합니다. 어느 날 철호는 어떤 자연수로 이루어진 원형 수열의 연속하는 부분 수열의 합으로 만들 수 있는 수가 모두 몇 가지인지 알아보고 싶어졌습니다. 원형 수열이란 일반적인 수열에서 처음과 끝이 연결된 형태의 수열을 말합니다. 예를 들어 수열 [7, 9, 1, 1, 4] 로 원형 수열을 만들면 다음과 같습니다.

 

 

 

원형 수열은 처음과 끝이 연결되어 끊기는 부분이 없기 때문에 연속하는 부분 수열도 일반적인 수열보다 많아집니다.

원형 수열의 모든 원소 elements가 순서대로 주어질 때, 원형 수열의 연속 부분 수열 합으로 만들 수 있는 수의 개수를 return 하도록 solution 함수를 완성해주세요.

 

문제 해결 방법

 

deque의 maxlen 속성을 이용하여 문제를 해결했다. 

deque의 maxlen 속성은 deque를 생성할때 maxlen에 값을 주면 해당 값만큼의 크기의 deq를 만들 수 있는 속성이다. 

 

만약 사용자가 해당 deque에 maxlen이상의 값을 추가하면 deq에 있는 맨 왼쪽의 값부터 삭제한다. 

(appendleft()를 할 경우, 맨 오른쪽의 원소가 삭제되고 맨 왼쪽에 값이 추가됨)

 

문제에서는 연속된 값의 길이가 1부터 elements의 크기 까지일 수 있다. 

따라서 해당 경우를 헤아려 가며 deq를 만들어주고 deq 요소의 값을 합해준 후, 해당 값을 하나의 리스트에 넣었다. 

 

중복값에 대한 처리는 set으로 해줬다. 

 

코드 구현

 

from collections import deque

def solution(elements):
    answer = 0
    a = []
    for i in range(1,len(elements)+1) :
        deq = deque(maxlen=i)
        
        for i in elements * 2 :
            deq.append(i)
            a.append(sum(deq))
            
    
            
        
    
    return len(set(a))

 

 

시간/공간 복잡도

 

최악의 경우 O(N^2)

 

 

최적화 및 개선 / 어려웠던 점

 

사실 이 문제를 3중 for문으로 풀었는데 아니나 다를까, 테스트 케이스 5번부터 끝까지 시간초과가 났다. 

 

근데 아무리 생각해봐도 3중으로 for문을 사용하지 않으면 문제를 풀 수 있는 방법을 떠올릴 수 없었다. 

 

힌트를 얻어 문제를 풀었다. deque에 maxlen이라는 속성이 있는지 처음 알았다. 최고다!

https://school.programmers.co.kr/learn/courses/30/lessons/12914#

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

효진이는 멀리 뛰기를 연습하고 있습니다. 효진이는 한번에 1, 또는 2칸을 뛸 수 있습니다. 칸이 총 4개 있을 때, 효진이는

(1, 1, 1, 1)

(1, 2, 1)

(1, 1, 2)

(2, 1, 1)

(2, 2)

5가지 방법으로 맨 끝 칸에 도달할 수 있습니다. 멀리뛰기에 사용될 칸의 수 n이 주어질 때, 효진이가 끝에 도달하는 방법이 몇 가지인지 알아내, 여기에 1234567를 나눈 나머지를 리턴하는 함수, solution을 완성하세요. 예를 들어 4가 입력된다면, 5 return하면 됩니다.

 

문제 해결 방법

 

n이 1일때, 2일때, 3일때, 4일때의 결과를 문제에서 찾고, 5일때 결과를 만들어서 보니 피보나치 수열의 형태를 띄었다. 

피보나치 수열을 구현하여 해당문제를 해결했다. 

 

 

코드 구현

 

import itertools

def solution(n):
    answer = 0
    tmp=[0, 1, 1]
    cnt = 3
    summ = 0
    while 1:
        if n == 1:
            answer = 1
            return answer % 1234567
        elif n == 2:
            answer = 2
            return answer % 1234567
        else:
            summ = (tmp[cnt-1] + tmp[cnt-2]) 
            tmp.append(summ)
            cnt+=1
        
        if cnt == n+2:
            return summ % 1234567
    
    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 / 어려웠던 점

 

입출력의 경우를 쭉 나열해서 문제를 풀어볼 생각을 못하고, 직접 문제 그대로 구현해보려 했다. 

문제 그대로 구현하니 테스트케이스 2번부터 끝까지 시간초과가 났다. 

아무리 생각해봐도 이중 반복문을 사용하지 않고 문제를 해결할 방법이 생각나지 않아서, 힌트를 봤다. 

 

문제가 안풀리면 입출력문을 문제에서 제시한 부분을 나열해보고 그다음 부분은 직접 경우의 수를 구해 붙인뒤에 

점화식을 세워 문제를 풀 생각을 해봐야겠다. 

 

문제에 거의 점화식이 주어지는 경우도 있으니, 이런 부분 감안해서 문제를 읽어볼 것.

 

https://school.programmers.co.kr/learn/courses/30/lessons/12980#qna

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

OO 연구소는 한 번에 K 칸을 앞으로 점프하거나, (현재까지 온 거리) x 2 에 해당하는 위치로 순간이동을 할 수 있는 특수한 기능을 가진 아이언 슈트를 개발하여 판매하고 있습니다. 이 아이언 슈트는 건전지로 작동되는데, 순간이동을 하면 건전지 사용량이 줄지 않지만, 앞으로 K 칸을 점프하면 K 만큼의 건전지 사용량이 듭니다. 그러므로 아이언 슈트를 착용하고 이동할 때는 순간 이동을 하는 것이 더 효율적입니다. 아이언 슈트 구매자는 아이언 슈트를 착용하고 거리가 N 만큼 떨어져 있는 장소로 가려고 합니다. , 건전지 사용량을 줄이기 위해 점프로 이동하는 것은 최소로 하려고 합니다. 아이언 슈트 구매자가 이동하려는 거리 N이 주어졌을 때, 사용해야 하는 건전지 사용량의 최솟값을 return하는 solution 함수를 만들어 주세요.

 

예를 들어 거리가 5만큼 떨어져 있는 장소로 가려고 합니다.

아이언 슈트를 입고 거리가 5만큼 떨어져 있는 장소로 갈 수 있는 경우의 수는 여러 가지입니다.

 

처음 위치 0 에서 5 칸을 앞으로 점프하면 바로 도착하지만, 건전지 사용량이 5 만큼 듭니다.

처음 위치 0 에서 2 칸을 앞으로 점프한 다음 순간이동 하면 (현재까지 온 거리 : 2) x 2에 해당하는 위치로 이동할 수 있으므로 위치 4로 이동합니다. 이때 1 칸을 앞으로 점프하면 도착하므로 건전지 사용량이 3 만큼 듭니다.

처음 위치 0 에서 1 칸을 앞으로 점프한 다음 순간이동 하면 (현재까지 온 거리 : 1) x 2에 해당하는 위치로 이동할 수 있으므로 위치 2로 이동됩니다. 이때 다시 순간이동 하면 (현재까지 온 거리 : 2) x 2 만큼 이동할 수 있으므로 위치 4로 이동합니다. 이때 1 칸을 앞으로 점프하면 도착하므로 건전지 사용량이 2 만큼 듭니다.

위의 3가지 경우 거리가 5만큼 떨어져 있는 장소로 가기 위해서 3번째 경우가 건전지 사용량이 가장 적으므로 답은 2가 됩니다.

 

문제 해결 방법

 

N을 2로 나눌때 나눠 떨어지면 넘어가고 2로 나눠떨어지지 않을때 ans를 1씩 추가한다. 

만약 n이 1까지 도달하면 ans를 1 추가하고 ans를 리턴한다. 

 

문제에서 한번 점프할때 1칸, 2칸 혹은 N칸 간격 까지 할 수 있지만, 문제에서 제시한 설명처럼 1칸 점프하는게 효율적임을 알 수 있다. 따라서 점프는 1칸만 하는 경우만 고려한다. 

 

 

코드 구현

 

def solution(n):
    ans = 0
    
    
    while 1:
        if n == 1:
            ans+=1
            break
        
        if n % 2 == 0 :
            n = n // 2
        else:
            n = n - 1
            ans += 1
        
    
    return ans

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선 및 어려웠던 점

 

사실 이 문제 도저히 못풀겠어서 힌트를 참고했다. 


이런 식의 문제는 0에서 N으로 가는 코드를 작성할때보다.

N부터 시작해서 0 으로 갈때에 해결되는 경우가 많이 나오는 것을 힌트로 알게되었다. 

 

현재까지 온 거리가 2의 배수가 되므로 2로 나눠야 되는 것을 알게되었다.  만약 나눠떨어 지지 않으면 점프를 해야한다. 

(점프를 하면 1칸만 이동할 수 있으므로)

 

아직 이 문제가 직관적으로 와닿지 않는다.

이런 유형의 문제도 좀 많이 풀어봐야겠다. 

https://school.programmers.co.kr/learn/courses/30/lessons/178871

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

얀에서는 매년 달리기 경주가 열립니다. 해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때 추월한 선수의 이름을 부릅니다. 예를 들어 1등부터 3등까지 "mumu", "soe", "poe" 선수들이 순서대로 달리고 있을 때, 해설진이 "soe"선수를 불렀다면 2등인 "soe" 선수가 1등인 "mumu" 선수를 추월했다는 것입니다. "soe" 선수가 1, "mumu" 선수가 2등으로 바뀝니다.

 

선수들의 이름이 1등부터 현재 등수 순서대로 담긴 문자열 배열 players와 해설진이 부른 이름을 담은 문자열 배열 callings가 매개변수로 주어질 때, 경주가 끝났을 때 선수들의 이름을 1등부터 등수 순서대로 배열에 담아 return 하는 solution 함수를 완성해주세요.

 

 

 

문제 해결 방법

 

 

이문제 진짜 딕셔너리 순환을 위해서 이중 for문을 사용하지 않고, 하나의 반복문만 사용하고,

더이상의 반복문을 사용하지 않기 위해서, 딕셔너리 두개로 선수의 순위를 바로바로 바꿔주었다. 

 

 

코드 구현

 

def solution(players, callings):
    answer = []
    
    dicct={}
    dic={}
    for idx, i in enumerate(players):
        dicct[i]=idx
    
    for idx, i in enumerate(players):
        dic[idx]=i
        
    
    
    
#     print('dic', dic) # key는 숫자 
#     print('dicct', dicct) # key는 이름 
    
    for i in callings:
        value = dicct[i] # 숫자
        key = dic[value]
        
        value2 = dicct[i]-1
        key2 = dic[value2]
        
        
        dic[value] = key2
        dicct[key] = value2
        
        dic[value2] = key
        dicct[key2] = value
    
    for key, value in dic.items():
        answer.append(value)
    
    return answer

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선

시간초과가 났다. 

딕셔너리 전체 순환을 하면 안되나보다.

딕셔너리 두개로 반복문 하나만 사용해서 문제를 풀었다. 

하나의 딕셔너리로 key를 통한 검색을 위해 도중에 key와 value를 바꿔주고자 했지만, 해당 방법을 사용하면 또 반복문을 사용해야 해서 해당 방법은 사용할 수 없었다. 

 

 

어려웠던 점

 

막상 풀고보니 전체 순환을 안할 수 있다는게 넘 신기하다. 

 

https://school.programmers.co.kr/learn/courses/30/lessons/131128

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

 

두 정수 X, Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 ≤ k ≤ 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다). X, Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다. X, Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다.

 

예를 들어, X = 3403이고 Y = 13203이라면, X Y의 짝꿍은 X Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로 X = 5525이고 Y = 1255이면 X Y의 짝꿍은 X Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5 3, Y에는 5 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.)

두 정수 X, Y가 주어졌을 때, X, Y의 짝꿍을 return하는 solution 함수를 완성해주세요.

 

문제 해결 방법

 

순회를 통한 문제 해결 

 

 

코드 구현

from collections import deque
def solution(X, Y):
    answer = ''
    
    tem = []
    
    Y=list(Y)
    Y.sort()
    
    X=list(X)
    X.sort()
    
    y = deque(Y)
    
    new = deque()
    cnt = 0
    for idx, i in enumerate(X):
        while 1:
            if cnt == len(y):
                break

            t= y[cnt]
            if i == t:
                del y[cnt]
                tem.append(t)
                break
            else:
                if y[cnt]<i:
                    cnt+=1
                else:
                    break
    
    if len(tem) == 0:
        return '-1'
    else:
        cntt = 0
        check = 0
        while 1:
            if cntt == len(tem):
                break
                
            if check == 1:
                break
            
            if tem[cntt] =='0':
                check = 0
                cntt +=1
            else:
                check =1
                
    if check == 0:
        return "0"
        
    tem.sort(reverse=True)
    answer = "".join(tem)
    
    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선

 

테스트케이스 11번~ 15번까지 실패했다. 

실패 이유는 시간초과였는데, 문제 조건에서 X, Y는 최대 300만 까지의 길이를 가질 수 있다고 했다. 

 

기존에 내가 작성한 코드는 X를 전부 돌면서 Y또한 전부 순회하도록 돼있었는데, 그러면 시간초과가 날 수 밖에 없는 상황이였다. 즉, 길이가 긴 대상을 전부 순회하지 않고 원하는 값을 찾아야 했다. 

 

한번의 순회로 각 숫자들의 개수를 셀 수 있어야 했다. 

 

어려웠던 점

 

길이가 긴 대상에 대한 고려를 생각해내지 못했다. 

이부분에 대해서 담엔 틀리지 말아야징 ㅎ,,

for i in range(10):
    length = int(input())
    check=[]
    for j in range(8):
        stringg = input()
        check.append(stringg)
    

    #print(check)
    answer = 0
    ccheck = 0
    if length % 2 == 0: # 짝수
        checkN = length // 2
        ccheck = 0
    else:
        checkN = ((length+1)//2)-1 # 홀수 한 가운데 
        ccheck = 1
    
    for one in check: # 가로 체크
        stackk = []
        if ccheck == 0:
            for idx, k in enumerate(one):
                if idx > len(one) - length:
                    break
                
                for ik in range(checkN):
                    stackk.append(one[idx+1])
                
                good = 0
                for jk in range(checkN):
                    print
                    if stackk.pop == one[checkN+idx+1]:
                        good = 1
                    else:
                        good = 0
                        break
                    
                if good == 1:
                        answer+=1
        else:
            for idx, k in enumerate(one):
                if idx > len(one) - length:
                    break
                
                for ik in range(checkN):
                    stackk.append(one[idx+1])
                
                good = 0
                stackk.pop()

                for jk in range(checkN-1):
                    if stackk.pop == one[checkN+idx+1]:
                        good = 1
                    else:
                        good = 0
                    
                if good == 1:
                        answer+=1
    
    for p in range(8): # 세로 체크
        stackk = []
        if ccheck == 0:
            for idx, two in enumerate(check):
                if idx > len(two) - length:
                    break

                for ik in range(checkN):
                    stackk.append(check[idx+ik][p])
                
                good = 0
                for jk in range(checkN):
                    if stackk.pop == check[checkN+idx+jk][p]:
                        good = 1
                    else:
                        good = 0
                    
                if good == 1:
                        answer+=1
        else:
            # 홀수 
            for idx, two in enumerate(check):
                if idx > len(two) - length:
                    break
                
                for ik in range(checkN):
                    stackk.append(check[idx+ik][p])
                
                good = 0
                stackk.pop()
                for jk in range(checkN-1):
                    if stackk.pop == check[checkN+idx+jk][p]:
                        good = 1
                    else:
                        good = 0
                    
                if good == 1:
                        answer+=1


    
    
    print("#"+str(i+1), str(answer))

https://swexpertacademy.com/main/code/problem/problemDetail.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

문제 해결 방법 및 코드 구현

 

N = int(input())

for i in range(N):
    stringg=""
    n, a, b = input().split()
    n = int(n)
    a = int(a)
    b = int(b)

    so = 0
    dae = 0
    if a+b <= n:
        so = 0
    else:
        so = abs(a+b) - n

    if a>= b:
        dae = b
    else:
        dae = a

    if a == b == n:
        so = a
        dae = b
    
    if a == b and a != n:
        dae = a

    
    stringg="#"+str(i+1)+" "+ str(dae)+" "+ str(so)
    print(stringg)

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선

따로 하지않음

 

 

어려웠던 점 / 느낀점

 

애매하게 테스트케이스를 절반만 맞추고 이랬는데, 별 다르게 고쳐나갈 방법을 생각할 수 없었다. 

테스트케이스로 들어갈만한 실제 값을 임의로 넣어보는 수 밖에 없었다. 

사실 프로그래머스로 공부하다보면 질문하기 기능에 의존하게 되는데, swea는 질문 할 수도 없고 사람들이 댓글로 힌트를 달지 않은 경우, 오로지 혼자 힘으로 테스트케이스를 만들어서 적용해보는 수 밖에 없다. 

코테 칠때 도움 많이 될 듯

 

D3 정답률 70.12로 시작했으니  80으로 가봐야겠다. 

https://swexpertacademy.com/main/code/problem/problemDetail.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

문제 해결 방법 및 코드 구현

 


t = int(input())

for i in range(t):
    stringg = input()
    stackk = []
    check = 0
    prin = ""
    if len(stringg) % 2 == 0:
        #짝수
        checkN = (len(stringg) // 2) - 1
        for idx, j in enumerate(stringg):
            if idx <= checkN:
                stackk.append(j)
            else:
                if stackk.pop() == j:
                    check = 1
                else:
                    check = 0
    else:
        #홀수
        checkN = (len(stringg) - 1) // 2
        for idx, j in enumerate(stringg):
            if idx < checkN:
                stackk.append(j)
            elif idx == checkN:
                pass
            else:
                if stackk.pop() == j:
                    check = 1
                else:
                    check = 0
    
    
    prin +="#"+str(i+1)+" "+str(check)
    print(prin)

 

 

시간/공간 복잡도

 

최악의 경우 O(N)

 

 

최적화 및 개선

따로 하지않음

 

 

어려웠던 점 / 느낀점

 

D3으로 가야겠다.

https://school.programmers.co.kr/learn/courses/30/lessons/12952

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제설명

 

가로, 세로 길이가 n인 정사각형으로된 체스판이 있습니다. 체스판 위의 n개의 퀸이 서로를 공격할 수 없도록 배치하고 싶습니다.

 

예를 들어서 n 4인경우 다음과 같이 퀸을 배치하면 n개의 퀸은 서로를 한번에 공격 할 수 없습니다.

 

 

 

체스판의 가로 세로의 세로의 길이 n이 매개변수로 주어질 때, n개의 퀸이 조건에 만족 하도록 배치할 수 있는 방법의 수를 return하는 solution함수를 완성해주세요.

 

문제 해결 방법

 

일단 백트래킹으로 문제를 구현할 생각을 했다. 

그리고 체스판을 1차원으로 생각하려 했다. 

0부터 n까지의 행에 대해서 차례대로 들어가는 값은 하나의 n크기의 리스트에 담을 수 있다. 

 

반복문으로 0부터 n까지의 행을 조회한다. 하나의 행에 대한 열을 모두 조회한다. 

조회를 마치면 다음 행으로 넘어가 그 행에 대한 열을 모두 조회한다. 

.

단, 조회시 조건이 붙는다. 

퀸의 특성은 위 아래 양 옆, 하나의 말에서 나갈 수 있는 대각선 모든 방향 즉, 8개의 방향으로 체스판 끝까지 공격이 가능하다. 

 

하나의 행의 특정 열에 대해서 다음 행은 그 특정 열과 같으면 안된다.  (공격당함)

대각선을 구분하는 방법은 가려는 위치와 기존에 있던 말들의 위치에 대해서 가로 간격과 세로간격이 같으면 대각선이되니 그자리는 못가는 자리다. (공격당함)

 

이렇게 조회하는 과정을 백트래킹을 통해 조회한다면, 불필요한 조회를 줄일 수 있을 것이다. 

 

 

 

코드 구현

 

 

 

def solution(n):
    answer = []
    # 퀸은 위, 아래, 양옆, 대각선으로 공격할 수 있음
    check = []
    
    def backTrack(check, cnt, answer):
        #print(len(answer), check, cnt ,'check, cnt, answer')
        if cnt >= n and len(check) >= n:
            answer.append(check)
            return answer
        
        for row in range(n):
            if row not in check: # 같은 행인지 체크 
                contition = 0
                for idx,i in enumerate(check):
                    if abs(row - i) == abs(cnt - idx):
                        contition = 1
                        break
                    else:
                        contition = 0
                    
                if contition == 0:
                    check.append(row)
                    cnt += 1
                    backTrack(check, cnt, answer)
                    cnt -= 1
                    check.pop()
                    
    cnt = 0
    for col in range(n):
        check.append(col)
        cnt += 1
        backTrack(check, cnt, answer)
        check.pop()
        cnt -= 1
    
    #print('answer', answer)
    
    answer = len(answer)
    
    return answer

 

 

시간/공간 복잡도

 

최악의 경우 O(N!)

 

 

최적화 및 개선

따로 하지않음

 

 

어려웠던 점

 

저번주인가 진짜 백트래킹 너무 어려워서 토나올뻔 했는데, 이제 좀 괜찮다. 신기하다.

N-Queen문제 예전에는 진짜 손도 못댔는데, 이번에는 혼자 잘 풀어서 기분이 아주 최고다 야호~~~~~~~~~~~~~~

(쫌만 더하면 풀릴 것 같고 그래서 3시간 잡고 있었던건 안비밀)

+ Recent posts