[Codility]Lesson12/Euclidean algorithm/ChocolatesByNumbers

Mijeong Ryu·2023년 5월 27일
0

Codility

목록 보기
10/17

문제

Two positive integers N and M are given. Integer N represents the number of chocolates arranged in a circle, numbered from 0 to N − 1.

You start to eat the chocolates. After eating a chocolate you leave only a wrapper.

You begin with eating chocolate number 0. Then you omit the next M − 1 chocolates or wrappers on the circle, and eat the following one.

More precisely, if you ate chocolate number X, then you will next eat the chocolate with number (X + M) modulo N (remainder of division).

You stop eating when you encounter an empty wrapper.

For example, given integers N = 10 and M = 4. You will eat the following chocolates: 0, 4, 8, 2, 6.

The goal is to count the number of chocolates that you will eat, following the above rules.

Write a function:

class Solution { public int solution(int N, int M); }

that, given two positive integers N and M, returns the number of chocolates that you will eat.

For example, given integers N = 10 and M = 4. the function should return 5, as explained above.

Write an efficient algorithm for the following assumptions:

N and M are integers within the range [1..1,000,000,000].
Copyright 2009–2023 by Codility Limited. All Rights Reserved. Unauthorized copying, publication or disclosure prohibited.

코드1

// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
import java.util.*;
class Solution {
    public int solution(int N, int M) {
        ArrayList<Integer> ateList = new ArrayList<>();
       ateList.add(0);
       int answer = 0;
        for(int i=1; i<Integer.MAX_VALUE; i++){
            if(M*i>=N){
              if(ateList.contains((M*i)%N)){
                  break;
              }
              ateList.add((M*i)%N);   
            }
            else{
                if(ateList.contains(M*i)){
                  break;
                }
                ateList.add(M*i);
            }
        }
        answer = ateList.size();
        return answer;
        }

        // Implement your solution here
    
}

코드2

// you can also use imports, for example:
// import java.util.*;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
import java.util.*;
class Solution {
    public int solution(int N, int M) {
    // ~N 중에 최대공약수의 배수 갯수수
    int answer = 0;
    answer = (N / getGCD(M,N)) ;
    return answer;
    }

    //N과 M의 최대공약수 구하기
    public int getGCD(int N, int M){
        if(M==0){
            return N;
        }
        else{
            return getGCD(M,N%M);
        }
    }
}

풀이

코드1은 반복문을 돌면서, N보다 작은 경우 배수를 list에 담고
N보다 큰경우, 나머지를 list에 담은 후에
list에 이미 그 값이 있으면 반복문을 빠져나와 리스트의 size를 리턴하도록 구현했다.
이 경우, 정확도는 100이지만 시간복잡도 문제로 fail 이다.

시간복잡도 문제를 해결 하기 위해, 문제를 더 분석해보면
예시의 경우 결국 2의 약수로 초콜릿을 먹게된다.
즉 4와 10의 최대공약수 2의 배수들을 제거하면 된다.
getGCD를 통해 최대공약수를 구한다.(유클리드 알고리즘 참고)

참고

최대공약수 구하기

function gcd(x, y) {

    if(y === 0) return x; //y가 0이면 x값 반환
    
    return gcd (y, x % y);
    
}

0개의 댓글