본문으로 바로가기

책을보다가 생각지도 못한 방법이 보여서 요약 글을씁니다.

계속 고민했다면 같은 방식으로 풀었을듯

 

책 제목은 : 알고리즘 문제 해결 전략 1

 

다이어트 현황 파악

 

시간에 따라 관찰된 숫자들이 주어질때 M-이동 평균은 마지막 M개의 관찰 값의 평균으로 정의됩니다.

따라서 새로운 관찰값이 나오면 M-이동평균은 새 관찰 값을 포함하도록 바꿉니다.

 

a = 50.3, 50.6, 50.4, 50, 49.5, 49.3, 50.3, 50.6, 50.4, 50, 49.5, 49.3

m = 3

제 1년간 1달간격 가상의 몸무게 기록입니다.

여기서 3달간격의 평균을 구해봅시다.

 

a = 몸무게 리스트

m = 평균 기간

 

a개의 측정치가 주어질때 m달간의 이동편균을 계산하는 프로그램을 어떻케 짜야 할까요 ?

각 위치에서 지난 m개 측정치의 합을 구하고 이를 m으로 나누면 됩니다.

 

이때 이 코드는 두개의 for문에 의해 지배됩니다.

    public List<Double> movingAverage1(List<Double> a, int m){
        List<Double> ret = new ArrayList <>();

        int n = a.size();

        int  cnt = 0;
        for(int i=m-1;i<n;i++){
            double sum = 0d;
            for(int j=0;j<m;j++){
                sum += a.get(i-j);
                cnt++;
            }
            ret.add(sum/m);
        }
        System.out.println(cnt); //30

        return ret;
    }

j를 사용하는 반복문은 항상 m번 실행되고 i를 사용하는 반복문은 a-m+1 번 실행되니

전체 반복문은 m x (n-m+1) 번 반복됩니다.

 

a = 12 이고 m = 3 이니 반복횟수는 당연히 30번입니다.

 

하지만 이건 선형시간 알고리즘이 아닙니다.

 

O(n) 을 충족하지못합니다.

 

또 다른 방법으로는

다시 생각해보면

측정치가 m개는 되어야 이동 평균을 계산할 수 있으니, 태어난 이후 m-1 일부터 이동평균을 계산 할 수 있습니다.

이때 m-1 일의 이동평균과 m일의 이동 평균에 포함되는 숫자들은

0일과 m일의 몸무게를 제외하면 전부 겹친다는것을 알 수 있습니다.

 

그러면 측정한 몸무게의 합을 일일히 구할것없이 m-1 일에 구했던 몸무게의 합에서 0일째에 측정한 몸무게를 빼고

m일째에 측정한 몸무게를 더하면 어떨까요 ?

 

이 아이디어를 구현하면  아래코드를 구할수 있습니다.

 

    public List<Double> movingAverage2(List<Double> a, int m){
        List<Double> ret = new ArrayList <>();

        int n = a.size();

        int  cnt = 0;
        double sum = 0d;
        for(int i=0;i<m-1;i++){
            sum+=a.get(i);
            cnt++;
        }

        for(int i=m-1;i<n;i++){
            sum+=a.get(i);
            ret.add(sum/m);
            sum-=a.get(i-m+1);
            cnt++;
        }
        System.out.println(cnt); //12

        return ret;
    }

 

하나로 묶여서 반복하던 두개의 반복문을 두개로 분리했습니다.

이 알고리즘의 반복문 횟수는

m-1(m-1)+(a-m+1) = a.size() 가 됩니다.

 

수행시간은 입력값에 정비례하게되었습니다.

입력의 크기에 대비해 걸리는 시간을 그래프로 그려보면 정확히 직선이 유지됩니다.

때문에 이런 알고리즘을 선형시간 알고리즘이라고 부릅니다.

 

선형시간에 실행되는 알고리즘은 대개 우리가 찾을 수 있는 알고리즘 중 가장 좋은 알고리즘입니다.

 

'Algo' 카테고리의 다른 글

시간복잡도 분석  (0) 2020.11.04