[스크랩] 최대 연속 부분 구간 합 문제를 푸는 알고리즘

2016. 6. 27. 14:45·알고리즘

아래의 예제는 '프로그래밍 대회에서 배우는 알고리즘 문제 해결 전략' 이라는 책의 미리보기에서 확인할 수 있는 내용이다.

이를 통해 효율적인 알고리즘을 구성하면 수행시간이 얼마나 짧아 질 수 있는 가를 확인할 수 있다.



{ -7, 4, -3, 6, 3, -8, 3, 4 } 에서 최대의 합을 갖는 구간을 찾아서, 최대의 합을 출력하는 문제이다.

책의 예제를 Java 로 수정하면 아래와 같다.


알고리즘 구성에 따라 for 문을 한번만 사용하고서 답을 찾을 수도 있다.

이렇게 효율적인 알고리즘을 구성하는 것은 무엇보다 중요하다.



package algorithm;

public class EfficientMaxSum {

    static int[] array = { -7, 4, -3, 6, 3, -8, 3, 4 };

    // A[] 의 연속된 부분 구간의 최대 합을 구한다. 시간 복잡도: $O(N^3)$
    public static int inefficientMaxSum(int[] A) {
        int N = A.length;
        int ret = Integer.MIN_VALUE;

        for (int i = 0; i < N; ++i)
            for (int j = i; j < N; ++j) {
                // 구간 A[i..j]의 합을 구한다.
                int sum = 0;
                for (int k = i; k <= j; ++k)
                    sum += A[k];

                ret = Math.max(ret, sum);
            }

        return ret;
    }

    public static int betterMaxSum(int[] A) {
        int N = A.length;
        int ret = Integer.MIN_VALUE;

        for (int i = 0; i < N; ++i) {
            int sum = 0;
            for (int j = i; j < N; ++j) {
                // 구간 A[i..j]의 합을 구한다.
                sum += A[j];
                ret = Math.max(ret, sum);
            }
        }
        return ret;
    }

    // 최대 연속 부분 구간 합 문제를 푸는 분할 정복 알고리즘
    // A[lo..hi]의 연속된 부분 구간의 최대 합을 구한다. 시간 복잡도: O(nlgn)
    public static int fastMaxSum(int[] A, int lo, int hi) {
        // 기저 사례: 구간의 길이가 1일 경우
        if (lo == hi)
            return A[lo];
        // 배열을 A[lo..mid], A[mid+1..hi]의 두 조각으로 나눈다.
        int mid = (lo + hi) / 2;
        // 두 부분에 모두 걸쳐 있는 최대 합 구간을 찾는다. 이 구간은
        // A[i..mid]와 A[mid+1..j] 형태를 갖는 구간의 합으로 이루어진다.
        // A[i..mid] 형태를 갖는 최대 구간을 찾는다.
        int left = Integer.MIN_VALUE;
        int right = Integer.MIN_VALUE;
        int sum = 0;

        for (int i = mid; i >= lo; --i) {
            sum += A[i];
            left = Math.max(left, sum);
        }
        // A[mid+1..j] 형태를 갖는 최대 구간을 찾는다.
        sum = 0;
        for (int j = mid + 1; j <= hi; ++j) {
            sum += A[j];
            right = Math.max(right, sum);
        }
        // 최대 구간이 두 조각 중 하나에만 속해 있는 경우의 답을 재귀 호출로 찾는다.
        int single = Math.max(fastMaxSum(A, lo, mid), fastMaxSum(A, mid + 1, hi));
        // 두 경우 중 최대치를 반환한다.
        return Math.max(left + right, single);
    }

    //  최대 연속 부분 구간 합 문제를 푸는 동적 계획법 알고리즘
    // A[] 의 연속된 부분 구간의 최대 합을 구한다. 시간 복잡도: O(n)
    public static int fastestMaxSum(int[] A) {
        int N = A.length;
        int ret = Integer.MIN_VALUE;
        int psum = 0;

        for (int i = 0; i < N; ++i) {
            psum = Math.max(psum, 0) + A[i];
            ret = Math.max(psum, ret);
           
//            System.out.println("-------------------------");
            System.out.printf("%2d, %2d, %2d\n", A[i], psum, ret);
//            System.out.println("-------------------------");
        }
        return ret;
    }

    public static void main(String[] args) {

        System.out.println(fastestMaxSum(array));
    }
}


http://book.algospot.com/estimation.html


반응형
저작자표시 비영리 (새창열림)

'알고리즘' 카테고리의 다른 글

[알고리즘] 백트래킹  (0) 2016.07.15
[스크랩] 나는 어떻게 알고리즘을 공부했을까?  (1) 2016.06.30
[스크랩] 문제 해결을 위한 창의적 알고리즘  (2) 2016.06.24
[JAVA] 순열(Permutation) 만들기  (0) 2016.06.13
[Java] 그래프 탐색법, 깊이우선탐색, 너비우선탐색  (0) 2016.06.09
'알고리즘' 카테고리의 다른 글
  • [알고리즘] 백트래킹
  • [스크랩] 나는 어떻게 알고리즘을 공부했을까?
  • [스크랩] 문제 해결을 위한 창의적 알고리즘
  • [JAVA] 순열(Permutation) 만들기
hs_seo
hs_seo
Hello World!
    반응형
  • hs_seo
    개발자로 살아남기
    hs_seo
  • 전체
    오늘
    어제
    • 전체 (1140)
      • 개발자 (21)
        • 개발에 유의할 점 (0)
        • 면접 (5)
      • IT 소식 (5)
        • 업계 (1)
      • java (51)
        • 디자인패턴 (3)
        • apache-common (1)
      • 개념 (47)
        • 자료구조 (4)
        • 함수형사고 (8)
        • 디자인패턴 (1)
      • 데이터분석 (1)
      • python (67)
        • 코드조각 (12)
        • 라이브러리 (2)
      • 빅데이터 (418)
        • zookeeper (5)
        • hadoop (78)
        • hdfs (12)
        • hive (127)
        • hbase (16)
        • spark (40)
        • scala (4)
        • trino (3)
        • oozie (41)
        • Hue (9)
        • R (5)
        • sqoop (6)
        • flume (3)
        • elasticsearch (2)
        • airflow (16)
        • kafka (3)
        • kubernetes (10)
        • openstack (3)
        • flink (2)
        • redis (2)
      • 빅데이터 강좌 (2)
      • 알고리즘 (131)
        • 알고리즘 (1)
        • 백준 (61)
        • 정올 (41)
        • 더블릿 (5)
        • 프로그래머스 (1)
      • 프로그래밍 언어 (30)
        • go (4)
        • js (9)
        • .Net (6)
        • Jsp (1)
        • ansible (3)
        • terraform (6)
      • Tools (56)
        • docker (2)
        • macbook (6)
        • maven (3)
        • sublime (1)
      • 프레임워크 (25)
        • [JS] angularjs (2)
        • [JS] node.js (19)
        • [Java] spring (2)
        • Android (2)
      • 데이타베이스 (43)
        • SQLD (5)
        • Oracle (1)
        • MySQL (8)
        • ADsP (2)
      • 리눅스 (25)
        • Bash (61)
      • GCP (5)
      • AWS (34)
        • EC2 (2)
        • EMR (14)
      • 정보보안기사 (4)
        • 네트워크 (1)
      • 개인 (80)
        • 업무실수 (0)
        • 책 (9)
        • 교육 (3)
        • 여행 (17)
        • 영화 (12)
        • 음악 (2)
        • 피규어 (4)
        • 게임 (3)
        • 생각 (7)
        • 기타 (10)
        • 좋은글 (5)
        • 좋은 사이트 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

    • 빅데이터-하둡,하이브로 시작하기
    • 빅데이터-스칼라, 스파크로 시작하기
    • Kaggle에서 파이썬으로 데이터 분석 시작하기
    • 쉘스크립트 개발 시작하기
    • 개발자가 데이터 분석 준전문가 되기
    • 데브쿠마
  • 공지사항

  • 인기 글

  • 태그

    HDFS
    error
    HIVE
    build
    bash
    다이나믹
    파이썬
    SPARK
    oozie
    airflow
    알고리즘
    nodejs
    AWS
    정올
    백준
    hbase
    ubuntu
    yarn
    mysql
    S3
    Hadoop
    하둡
    Linux
    java
    오류
    Tez
    emr
    Python
    k8s
    하이브
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
hs_seo
[스크랩] 최대 연속 부분 구간 합 문제를 푸는 알고리즘
상단으로

티스토리툴바