Eat Study Love

먹고 공부하고 사랑하라

Coding_Practice

MaxProfit(Given a log of stock prices compute the maximum possible earning)

eatplaylove 2024. 10. 30. 12:47

https://app.codility.com/programmers/lessons/9-maximum_slice_problem/max_profit/

 

MaxProfit coding task - Learn to Code - Codility

Given a log of stock prices compute the maximum possible earning.

app.codility.com

An array A consisting of N integers is given. It contains daily prices of a stock share for a period of N consecutive days. If a single share was bought on day P and sold on day Q, where 0 ≤ P ≤ Q < N, then the profit of such transaction is equal to A[Q] − A[P], provided that A[Q] ≥ A[P]. Otherwise, the transaction brings loss of A[P] − A[Q].

For example, consider the following array A consisting of six elements such that:

A[0] = 23171 A[1] = 21011 A[2] = 21123 A[3] = 21366 A[4] = 21013 A[5] = 21367

If a share was bought on day 0 and sold on day 2, a loss of 2048 would occur because A[2] − A[0] = 21123 − 23171 = −2048. If a share was bought on day 4 and sold on day 5, a profit of 354 would occur because A[5] − A[4] = 21367 − 21013 = 354. Maximum possible profit was 356. It would occur if a share was bought on day 1 and sold on day 5.

Write a function,

def solution(A)

that, given an array A consisting of N integers containing daily prices of a stock share for a period of N consecutive days, returns the maximum possible profit from one transaction during this period. The function should return 0 if it was impossible to gain any profit.

For example, given array A consisting of six elements such that:

A[0] = 23171 A[1] = 21011 A[2] = 21123 A[3] = 21366 A[4] = 21013 A[5] = 21367

the function should return 356, as explained above.

Write an efficient algorithm for the following assumptions:

  • N is an integer within the range [0..400,000];
  • each element of array A is an integer within the range [0..200,000].

 

이번에도 다른 플랫폼에 있는 문제를 가져와봤다.

 

주식 가격과 관련된 코드인데, 처음엔 오? 하고 이거 잘만 이용하면 내가 원하던 자동매매 프로그램을 만들 수 있는가..? 했더만 알고보니 이미 나와 있는 주식정보를 가지고 최대의 이윤을 뽑아보라는 것이다.

 

예측이 아니라, 계산의 영역 ㅎㅎ..

 

1. Python

 

보아하니 매수/매도는 각 1회만 되는 거 같고..

코드를 효율적으로 짜라고 했는데, Naive한 방법만 생각이 난다.

def solution(A):
    # Implement your solution here
    # 매수 / 매도는 각 1회만 가능하다고 가정하는 듯
    # Recursive 인가..

    #worst case
    temp = min(A) - max(A)
    #과연 이게 efficient 한 것인가..
    for i in range(len(A)):
        for j in range(i+1,len(A)):
            temp = max(temp,A[j]-A[i])
    return temp

답도 틀리고,  Time Out이 발생해버렸다;;

틀린 답이야 temp의 min 값을 0으로 설정하면 될 거 같긴 한데 Time Out이 관건

 

def solution(A):
    # Implement your solution here
    temp = 0
    for i in range(len(A)):
        for j in range(i+1,len(A)):
            if A[j] - A[i] > temp :
                temp = A[j] - A[i]
    return temp

일단 for문을 2번 겹쳐서 써버리면,

 

그 안에서 continue 든 break 든 if문이든 어떤 조건을 걸어도 N^2 시간소요가 뜬다. 이건 어쩔 수 없는 부분인듯

 

그래서 시간을 줄일려면 반복문 실행 횟수 자체를 줄여야 한다.

 

 

현재 코드는 두 개의 중첩 루프를 사용하여 모든 가능한 구매일과 판매일을 비교하고 최대 수익을 찾는 방식으로, 시간 복잡도가 O(n2)O(n^2)이어서 비효율적입니다. 이 문제는 Kadane's algorithm을 응용한 방법으로 해결할 수 있으며, 시간 복잡도를 O(n)O(n)으로 줄일 수 있습니다.
다음은 효율적인 방법을 설명하고 코드로 작성한 예시입니다.

효율적인 접근법

  1. 배열을 한 번 순회하면서 각 날의 최소 가격을 저장하고, 해당 가격을 기준으로 최댓값을 갱신합니다.
  2. 현재 주가에서 최소 가격을 뺀 값이 현재의 최대 이익인지 확인하고, 더 큰 이익이 발견되면 갱신합니다.

 

Idea 싸움이었다. 위 문제를 for문 1회 사용으로 풀 수 있다니..!

def solution(A):
    # Implement your solution here
    if not A : return 0
    
    profit = 0
    min_val = A[0]
    for x in A :
        profit = max(profit,x-min_val)
        min_val = min(min_val,x)
    
    return profit

Time이 O(N)으로 깔끔하게 떨어진다.

 

 

2. C++

C++도 동일하게 처리해버리기

// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;
#include<vector>
using namespace std;

int solution(vector<int> &A) {
    // Implement your solution here
    if(A.empty()) return 0;

    int profit = 0;
    int temp_min = A[0];

    for(const int x : A){
        profit = max(profit,x-temp_min);
        temp_min = min(temp_min,x);
    }
    return profit;
}

 

 

3. C

C도 뭐.. 비슷한 맥락이다.

요런 찬라의 아이디어가 코드 퀄리티를 좌우한다.

 

좀 더 집중하고, 좀 더 경험해보자

 

#include <stdio.h>

int solution(int A[], int N) {
    if (N < 2) return 0;

    int min_price = A[0];
    int max_profit = 0;

    for (int i = 1; i < N; i++) {
        // 최대 이익 갱신
        if (A[i] - min_price > max_profit) {
            max_profit = A[i] - min_price;
        }
        // 최소 가격 갱신
        if (A[i] < min_price) {
            min_price = A[i];
        }
    }
    
    return max_profit;
}

int main() {
    int A[] = {23171, 21011, 21123, 21366, 21013, 21367};
    int N = sizeof(A) / sizeof(A[0]);
    printf("Max Profit: %d\n", solution(A, N));
    return 0;
}