728x90

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

 

프로그래머스

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

programmers.co.kr

 

 

간단한 문제다.
한 15분? 정도 만에 풀었다.

 

오랜만에 코딩테스트 감 잡을겸 워밍업 연습~~

 

<풀이 코드>

import java.util.*;
import java.io.*;

class Solution {
    public int solution(int n, int[] lost, int[] reserve) {
        int[] arr = new int[n+1];
        for(int i=1; i<=n; i++){
            arr[i] = 1;
        }
        for(int i=0; i<lost.length; i++){
            arr[lost[i]]--;
        }
        for(int i=0; i<reserve.length; i++){
            arr[reserve[i]]++;
        }
        
        for(int i=1; i<n; i++){
            if(arr[i]==0){
                if(arr[i-1]==2){
                    arr[i-1]=1;
                    arr[i]=1;
                }
                else if(arr[i+1]==2){
                    arr[i+1]=1;
                    arr[i]=1;
                }
                else
                    continue;
            }
        }
        
        if(arr[n]==0){
            if(arr[n-1]==2){
                arr[n-1]=1;
                arr[n]=1;
            }
        }
        
        
        int ans = 0;
        for(int i=1; i<=n; i++){
            if(arr[i]>=1)
                ans++;
        }
        return ans;
    
    }
}
728x90

'코테 > 프로그래머스' 카테고리의 다른 글

프로그래머스 최소직사각형(JAVA)  (0) 2023.04.12
프로그래머스 K번째수(JAVA)  (0) 2023.04.05
728x90

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

 

1041번: 주사위

첫째 줄에 N이 주어진다. 둘째 줄에 주사위에 쓰여 있는 수가 주어진다. 위의 그림에서 A, B, C, D, E, F에 쓰여 있는 수가 차례대로 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, 쓰여 있는 수

www.acmicpc.net

 

문제)

 

풀이)

n이 1개부터 4개까지 그림을 그려가면서 해결해 보려 했는데 규칙성을 발견하지 못하고 헤맸던 문제이다.

그래서 한참을 고민ㅠㅠ

 

 

이 문제를 풀기 위해서는 크게 3가지 단계로 이루어진다.

 

 

  1. 정육면체에서 한 주사위당 보일 수 있는 면의 개수는 1, 2, 3 중 하나임을 파악한다.
  2. 보이는 면의 개수당 해당 주사위의 개수를 구하는 규칙성을 찾는다.
  3. 주사위에서 마주보는 면을 제외하고 나머지는 모두 인접하다. 이를 이용해 보이는 면에 해당하는 최소 값을 구한다.

 

1 단계: 정육면체에서 한 주사위당 보이는 면의 개수

주사위를 정육면체로 쌓아 올렸을 때, 바깥쪽에 보이는 주사위의 면의 개수는 총 3가지다.

 

3개: 가장 쉽게 생각해 볼 수 있는 것으로 맨 상단(뚜껑)에 존재하는 가장 끝의 4개는 3개의 면이 보인다.

2개: 모서리 쪽에 위치한 부분 4세트 + 상단에 위치한 부분 4세트

1개: 상단의 가운데 부분 + 나머지 4면에서 가운데 부분

 

 

 

2 단계: 주사위 개수 구하는 규칙성 찾기

 

해당 그림은 4*4*4 짜리 정육면체를 그려보았다.

쓰여 있는 숫자는 해당 주사위가 보이는 면의 개수이고, 2개의 면이 보이는 곳은 초록색 형광표시했다.(2개짜리 개수 구하기 편하려고!)

 

 

 

 

 

 

 

 

  • 3개: 맨 상단 4개 => 4
  • 2개: 모서리 쪽에 위치한 부분(N-1) 4세트 + 맨 상단(N-2) 4세트 => 4(N-2) + 4(N-1)
  • 1개: 상단 가운데: (N-2)*(N-2) + 4면 가운데: (N-2)*(N-1) => (N-2)*(N-2) +4(N-2)*(N-1)

 

 

3 단계: 면의 최소값 구하기

주사위는 6면으로 마주보는 쌍을 구하면 3쌍이다.

이 3쌍 중에서 가장 작은 수를 각각 저장하면 6개 중 3개가 저장된다.

 

이를 오름차순으로 정렬후, 3면이 보이는 것은 3개를 모두 더한 것, 2면이 보이는 것은 앞에서부터 2개를 더한 것, 1면이 보이는 것은 제일 처음 부분을 사용하면 된다.

 

그 후 각 면이 보이는 주사위 개수별로 곱해준 후 모두 더한 후 출력하면 문제가 해결된다.

 

 

 

n = int(input())
dice = list(map(int, input().split()))

# 1, 2, 3면이 보이는 주사위 개수 세기
side1 = 4*(n-2)*(n-1) + (n-2)**2
side2 = 4*(n-2) + 4*(n-1)
side3 = 4
# 주사위에서 마주보는 면 중 작은 것 저장하는 리스트
min_li = []

if n == 1:
    print(sum(dice) - max(dice))

else:
    # 주사위의 마주보는 면을 쌍으로 만들고 그 중 작은 애 뽑아 저장
    # (마주 보는 애는 인접하지 않으므로 동시에 보일 수 없음)
    min_li.append(min(dice[0], dice[5]))
    min_li.append(min(dice[1], dice[4]))
    min_li.append(min(dice[2], dice[3]))
    min_li.sort()

    min1 = side1 * min_li[0]
    min2 = side2 * (min_li[0] + min_li[1])
    min3 = side3 * (min_li[0] + min_li[1] + min_li[2])

    s = min1 + min2 + min3
    print(s)
728x90

'코테 > greedy' 카테고리의 다른 글

[Greedy] 1이 될 때까지  (0) 2022.03.14
[Greedy] 숫자 카드 게임  (0) 2022.03.13
[Greedy] 큰 수의 법칙  (0) 2022.03.04
[Greedy] 거스름돈  (0) 2022.03.04
728x90

"이것이 코딩테스트다" 책 문제 _ greedy 책 문제

문제)

어떠한 수 N이 1이 될 때까지 다음의 두 과정 중 하나를 반복적으로 선택하여 수행하려고 한다. 단, 두 번째 연산은 N이 K로 나누어 떨어질 때만 선택할 수 있다.

 

  1. N에서 1을 뺀다.

  2. N을 K로 나눈다.

 

N과 K가 주어질 때 N이 1이 될 때까지 1번 혹은 2번의 과정을 수행해야 하는 최소 횟수를 구하는 프로그램을 작성해라.

 

입력조건

  • 첫째 줄에 N(2 <= N <= 100,000)과 K(2 <= K <= 100,000)가 공백으로 구분되며 각각 자연수로 주어진다. 이때 입력으로 주어지는 N은 항상 K보다 크거나 같다.

 

출력조건

  • 첫째 줄에 N이 1이 될 때까지 1번 혹은 2번의 과정을 수행해야 하는 횟수의 최솟값을 출력한다.

 

 

 

풀이)

N이 1이 되기 위해 횟수가 가장 최소가 되려면 빼는 것 보다 나누는 과정이 숫자를 1에 가장 빨리 도달하게 할 수 있는 방법이다.

즉, 나누기를 최대한 많이 실행하면 된다.

따라서 N을 K로 나누어 떨어질 때까지 뺀 후, K로 나누는 과정을 반복하면 된다.

 

예를 들어 N = 17, K = 3일 경우 연산 과정은 다음과 같다.

단계 연산 과정 N
0(초기)   N = 17
1 1 빼기 N = 16
2 1 빼기 N = 15
3 K로 나누기 N = 5
4 1 빼기 N = 4
5 1 빼기 N = 3
6 K로 나누기 N = 1

 

이를 구현한 코드는 다음과 같다.

N, K = map(int, input().split())
count = 0

while (N > 1) :
    if N % K == 0:
        N = N // K
    else:
        N -= 1
    count += 1

print(count)

N이 1이 될 때까지 진행하기 때문에 while문의 조건은 N이 1보다 클 때이다.

while문 내에서 N이 K로 나누어 떨어질 경우 N은 K로 나누었을 때 몫으로 되고, K로 나누어 떨어지는 경우가 아닐 때 N에서 1씩 뺀다.

이때 연산 횟수를 count 변수에 1씩 더하여 저장한다.

 

 

 

문제에서는 N의 범위가 10만 이하이므로, 일일히 1씩 빼도 문제가 없지만, N이 100억 이상일경우 효율성 문제가 발생할 수 있다. 따라서 N이 K의 배수가 되도록 한 번에 빼는 방식으로 작성할 수 있다.

 

정답 예시)

N, K = map(int, input().split())
count = 0

while True:
    target = (N // K) * K
    count += N - target
    N = target

    if N < K:
        break
    count += 1
    N //= K

count += (N - 1)
print(count)

target을 N보다 작지만 가장 큰, K로 나누어 떨어지는 수이고, count에 N과 target의 차이(N에서 1을 뺀 횟수)만큼 더해준다.

그리고 N을 다시 target으로 갱신해주고 K로 나누어준다. 이때, N이 K보다 작을 경우(몫이 계속 0이 되므로) while문에서 빠져나온다.

그리고 N이 1이 되기까지 횟수이므로 (N-1)만큼 count에 더해주면 된다.(N을 더할 경우 N이 0이 되어버린다.)

728x90

'코테 > greedy' 카테고리의 다른 글

[Greedy] 백준 1041 주사위  (0) 2022.06.05
[Greedy] 숫자 카드 게임  (0) 2022.03.13
[Greedy] 큰 수의 법칙  (0) 2022.03.04
[Greedy] 거스름돈  (0) 2022.03.04
728x90

"이것이 코딩테스트다" 책 문제 _ greedy 책 문제

문제)

여러 개의 숫자 카드 중에서 가장 높은 숫자가 쓰인 카드 한 장을 뽑는 게임이다.

단, 게임의 룰을 지키며 카드를 뽑아야 하고 룰은 다음과 같다. 게임의 룰에 맞게 카드를 뽑는 프로그램을 만들어라.

 

   1. 숫자가 쓰인 카드들이 N * M 형태로 놓여 있다. 이때 N은 행의 개수를, M은 열의 개수를 의미한다.

   2. 먼저 뽑고자 하는 카드가 포함되어 있는 행을 선택한다.

   3. 그다음 선택된 행에 포함된 카드들 중 가장 숫자가 낮은 카드를 뽑아야 한다.

   4. 따라서 처음에 카드를 골라낼 행을 선택할 때, 이후에 해당 행에서 가장 숫자가 낮은 카드를 뽑을 것을 고려하여 최종적으로 가장 높은 숫자의 카드를 뽑을 수 있도록 전략을 세워야 한다.

 

입력조건

  • 첫째 줄에 숫자 카드들이 놓인 행의 개수 N과 열의 개수 M이 공백을 기준으로 하여 각가 자연수로 주어진다. (1 <= N, M <= 100)
  • 둘째 줄부터 N개의 줄에 걸쳐 각 카드에 적힌 숫자가 주어진다. 각 숫자는 1이상 10,000 이하의 자연수다.

 

출력조건

  • 첫째 줄에 게임의 룰에 맞게 선택한 카드에 적힌 숫자를 출력한다.
입력 예시1)
3 3
3 1 2
4 1 4
2 2 2
출력 예시1)
2
입력 예시2)
2 4
7 3 1 8
3 3 3 4
출력 예시2)
3

 

 

 

풀이)

각 행마다 가장 작은 수를 찾은 후 그 중에서 가장 큰 수를 출력하면 된다.

N, M = map(int, input().split())
minimum = []
for i in range(N):
    L = list(map(int, input().split()))
    minimum.append(min(L))
print(max(minimum))

N, M을 입력 받아서 정수로 변환해주고, 각 행에서 가장 작은 수를 저장할 minimum이라는 리스트를 생성한다.

행의 수만큼 반복하여 각 행을 입력받으면 L이라는 list로 받고, min()을 이용하여 가장 작은 수를 minimum에 추가한다.

모든 행의 작은 수를 추가한 이후, max()를 이용하여 가장 큰 수를 출력해주면 된다.

 

이 문제는 앞에서 나온 문제에 비하면 매우 쉬운 난이도고, 답에서 나온 풀이도 비슷하기 때문에 생략한다.

728x90

'코테 > greedy' 카테고리의 다른 글

[Greedy] 백준 1041 주사위  (0) 2022.06.05
[Greedy] 1이 될 때까지  (0) 2022.03.14
[Greedy] 큰 수의 법칙  (0) 2022.03.04
[Greedy] 거스름돈  (0) 2022.03.04

+ Recent posts