ALGORITHM/Java algorithm

[JAVA][LeetCode][SlidingWindow|DP] #123. Best Time to Buy and Sell Stock III

호이호이호잇 2024. 4. 17. 17:50
728x90
반응형

문제 / 예시 / 제한조건

 

처음에 보고는 간단하게 생각했음.

 

122번 문제 푼 것에서 transcation 이 발생 할 때마다, 배열에 저장하고 

가장 큰 수 2개를 뽑아서 더하면 되는 문제라고 생각함

 

예를 들어, 

1  1  2  4  7  2  4  9  0

이렇게 있으면

buy 1 -> sell 4  : profit = 3

buy 2 -> sell 7  : profit = 5

buy 2 -> sell 9  : profit = 7

가 되고

가장 큰 두 수 7,5 를 더해서 12가 된다고 생각함.

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length <= 1) {
            return 0;
        }
        
        int[] savedProfit = new int[prices.length];
        int savingIndex = 0;

        int buyTime = 0, sellTime = 1;
        while (sellTime < prices.length) {
            if (prices[sellTime] < prices[buyTime]) {
                buyTime = sellTime;
                sellTime++;
            } else {
                if (sellTime < prices.length - 1 && prices[sellTime] > prices[sellTime + 1]) {
                    savedProfit[savingIndex] = prices[sellTime] - prices[buyTime];
                    savingIndex++;

                    buyTime = sellTime;
                    sellTime = buyTime + 1;
                } else if (sellTime >= prices.length - 1) {
                    savedProfit[savingIndex] = prices[sellTime] - prices[buyTime];
                    savingIndex++;

                    sellTime++;
                } else {
                    sellTime++;
                }
            }
        }

        Arrays.sort(savedProfit);

        return savedProfit[savedProfit.length-1] + savedProfit[savedProfit.length-2];
    }
}

 

근데 아니였다!! 두둔

 

1  2  4  2  5  7  2  4  9  0

 

이렇게 있으면

buy 1 -> sell 7  : profit = 6

buy 2 -> sell 9  : profit = 7

이렇게 가장 큰 두개의 transaction 이 발생한다.

 

어떻게 해야 할 지 감이 전혀 안잡혀서, 영상을 엄청 많이 봤다.

https://youtu.be/37s1_xBiqH0?si=zjHPF9FP0kQgI8Dz

https://youtu.be/gVavspgEHyM?si=XltrueYAezhrDQoI

https://youtu.be/q4Vr307dOzs?si=rMqYwb5o6aO9UnEe

 

나오면 있는 영상을 다 봤는데 위에 두개가 가장 도움이 되었다.

특히 첫 번째 영상은 이해가 안되서 한 5번은 본 듯

 

그러다가 갑자기 이해가 되서(?) 문제를 풀었다.

 

 


일단 발생 할 수 있는 Transcation 은

Buy -> Sell -> Buy -> Sell 이다.

 

그래서 2개의 Transcation으로 나누어 생각을 해보는 것이다.

 

1번째 Transcation은 왼쪽부터 Buy point 를 찾는 것으로 시작해서 가장 큰 profit을 찾으면 된다.

Buy point는 어떻게 찾는가?

가장 저점에 사서 고점에 파는 것이 가장 큰 이익을 남길 수 있다.

고로, 가장 저점(minimum) 이 올바른 Buy point로 지정하면 된다.

 

2번째 Transcation은 오른쪽 끝 지점에서 부터 Sell point를 찾는 것으로 시작해서 가장 큰 profit을 찾으면 된다.

그렇다면 Sell point를 어떻게 찾으면 좋을까?

가장 저점에 사서 고점에 파는 것이 가장 큰 이익이니까

가장 고점(maximum)이 올바른  Sell point가 되겠다.

 

이렇게하면 

1 st Transcation :

  1 1 2 4 2 5 7 2 4 9 0
min  1 1 1 1 1            
profit 0 0 1 3              

여기서 2의 경우에 profit값은 2-1 = 1 이지만, 가장 큰 profit값을 유지해서 적어준다. 고로 3!

  1 1 2 4 2 5 7 2 4 9 0
min  1 1 1 1 1 1 1 1 1 1 1
profit 0 0 1 3 3 4 6 6 6 8 8

이렇게 할 수 있다.

 

그리고 2nd Transaction은 오른쪽부터 해주면 된다.

  1 1 2 4 2 5 7 2 4 9 0
max                    9 0
profit                   0 0

이렇게 차근차근 채워주면

  1 1 2 4 2 5 7 2 4 9 0
max  9 9 9 9 9 9 9 9 9 9 0
profit 8 8 7 7 7 7 7 7 5 0 0

 

이렇게 완성된다!

 

그렇게 두 표에서 동시에 가장 큰 값을 갖고 있는 포인트를 찾아주면 그 포인트가 바로 두 거래를 나누는 포인트가 되는 것!

  1 1 2 4 2 5 7 2 4 9 0
profit 0 0 1 3 3 4 6 6 6 8 8
  1 1 2 4 2 5 7 2 4 9 0
profit 8 8 7 7 7 7 7 7 5 0 0

 

 

고롷게 하면 된다!

 

내 정답 코드

class Solution {
    public int maxProfit(int[] prices) {
        int maxProfit = 0;

        // 1. 1st transaction from left to right - find min.
        int[] left = new int[prices.length];
        int min = prices[0];

        left[0] = 0; // for memorization to remember maximum profit of 1st transaction.

        for(int i=1; i<prices.length; i++) {
            min = Math.min(min, prices[i]);
            left[i] = Math.max(left[i-1], prices[i] - min );
        }

        // 2. 2nd transaction from right to left - find max.
        int[] right = new int[prices.length];
        int max = prices[prices.length-1];

        right[prices.length-1] = 0; // for memorization to remember maximum profit of 2nd transaction.

        for(int i=prices.length-2; i>=0; i--) {
            max = Math.max(max, prices[i]);
            right[i] = Math.max(right[i+1], max - prices[i]);
        }

        // 3. find maxProfit
        for(int i=0; i<prices.length; i++) {
            maxProfit = Math.max(maxProfit, left[i] + right[i]);
        }

        return maxProfit;
    }
}

Time Complexity : O(n)
Space Complexity : O(n)

 

진짜 이거 이해하느라 3일동안 붙잡고 있었는데!!!

드디어!!!!

728x90
반응형