🏃‍♀️ 코테 연습

22. 온도의 최댓값 (1차원 배열 구간합 : 제한시간 1초)

ji-hyun 2021. 2. 4. 03:23

이 문제의 저작권은 인프런 강의 "it 취업을 위한 알고리즘 문제풀이 (with C/C++) : 코딩테스트 대비" 에 있습니다.

 

 

 

 

문제 22

 

매일 아침 9시에 학교에서 측정한 온도가 어떤 정수의 수열로 주어졌을 때, 연속적인 며칠 동안의 온도의 합이 가장 큰 값을 알아보고자 한다. 예를 들어, 다음과 같이 10일 간의 온도가 주어졌을 때, 3 -2 -4 -9 0 3 7 13 8 -3 모든 연속적인 이틀간의 온도의 합은 다음과 같다. (그림 생략)

 

이때, 온도의 합이 가장 큰 값은 21이다. 매일 측정한 온도가 정수의 수열로 주어졌을 때, 연속적인 며칠 동안의 온도의 합이 가장 큰 값을 계산하는 프로그램을 작성하시오.

 

 

 

입력예제

 

>> 10 2

3 -2 -4 -9 0 3 7 13 8 -3

 

 

출력예제

 

>> 21

 

 

 

 


* 새로 학습한 내용 - 벡터

 

vector 컨테이너는 자동으로 메모리가 할당되는 배열이다.

이 아이는 자료구조 스택이랑 비슷한 느낌! (맨 뒤쪽에서 삽입 push_back(), 삭제 pop_back()이 가능하다)

vector를 사용하기 위해서 헤더에 include<vector>를 추가해줘야 한다.

 

vector의 선언 : vector<[data type]> [변수이름] 이다.
ex) vector<int> v;

 

<vector의 생성자와 연산자>

  • vector<int> v;
    - 비어있는 vector v를 생성합니다.

  • vector<int> v(5);
    - 기본값(0)으로 초기화 된 5개의 원소를 가지는 vector v를 생성합니다.

  • vector<int> v(5, 2);
    - 2로 초기화된 5개의 원소를 가지는 vector v를 생성합니다.

  • vector<int> v1(5, 2);
    vector<int> v2(v1);
    - v2는 v1 vector를 복사해서 생성됩니다.
  • vector<int> v1; , vector<int> v2;  가 있고, 내부에 인자들이 있다고 했을때.

    연산자 : "==", "!=", "<", ">", "<=", ">=" 로 대소비교 가 가능합니다.


출처: https://blockdmask.tistory.com/70 [개발자 지망생]


+ )

이 문제에서는 바깥에서 char a[100001]을 선언하는 것이 아닌 벡터를 사용해주는데, 그 이유는 바깥에서 배열을 선언하면 2자릿수인 배열도 길이가 100000인 배열 크기 안에서 생성되기 때문에 메모리 낭비가 발생한다. 

따라서 동적으로 배열 크기를 할당할 수 있는 벡터를 선언해주면 메모리 낭비가 발생하지 않는다.

 

 

 

 

코드 짜보기 (시간 초과)

 

#include<stdio.h>
#include<vector>
using namespace std;

int main(){
	int n, k, i, j, sum=0, max=-2147000000;
    
    scanf("%d %d", &n, &k);
    vector<int> a(n);
    
    for(i=0; i<n; i++){
    	scanf("%d", &a[i]);
    }
    
    for(i=0; i<n-k; i++){       //이중 for문.. i의 시작점과 끝점을 먼저 지정
    	sum=0;
        for(j=i; j<i+k; j++){    //i의 시작점을 기준으로 i+K까지 더해주기
        	sum=sum+a[j];
        }
        if(sum>max) max=sum;
     }
     printf("%d\n", max);
     return 0;
     
     }

 

예를 들어, n이 100000, k가 30000이라고 해보자.

그럼 a[0] + a[1] + a[2] + .... + a[29999] , a[1] + a[2] + a[3] + ... + a[30000] , ........ , a[70000] + a[70001] + a[70003] + ... + a[99999] 이런 식으로 들이 구해진다. 이는 이중 for문으로 코드를 짤 경우, 약 70000 * 30000번의 횟수로 돌아간다. Time Limited.. 

시간 초과로 실패한 코드이지만 한 번 학습해보면 좋을 것 같다.

 

 

 

 

 

코드 짜보기 (이중 for문을 사용하지 않고!)

아이디어 : sum + a[i] + a[i-k]

#include <stdio.h>
#include <vector>
using namespace std;

int main(){
	//freopen("input.txt", "rt", stdin);
	int n, k, i, sum=0, max;
	
    scanf("%d %d", &n, &k);
	vector<int> a(n);  //동적으로 배열 크기 할당
	
	for(i=0; i<n; i++){
		scanf("%d", &a[i]);
	}	
    
	for(i=0; i<k; i++){  //첫번째 배열 합 구해주기
		sum+=a[i];
	}
	max = sum;           //max에 할당
	for(i=k; i<n; i++){     //k부터 sum에 더해주기
		sum = sum+(a[i]-a[i-k]);   //단 i-k번째는 빼주기
		if(sum>max) max=sum;     //크기 비교
	}
	printf("%d\n", max);
	return 0;
}

 

이중 for문으로 배열의 합들을 매번 더해서 비교하는 것보다 첫번째 배열의 합을 구해준 후 k자리부터 하나 더해주기, 맨 앞에 있는 것은 빼주기 방법이 오히려 효율적으로 작동하는 것을 알 수 있다.

 

 

 

'🏃‍♀️ 코테 연습' 카테고리의 다른 글

25. 석차 구하기  (0) 2021.06.11
24. Jolly Jumpers  (0) 2021.06.10
23. 연속 부분 증가수열  (0) 2021.06.09
13. 가장 많이 사용된 자릿수  (0) 2021.01.15
12. 숫자의 총 개수(large : 제한시간 1초)  (0) 2021.01.13