0% completed
You are given two 0-indexed arrays, prices
and profits
, both of length n
. There are n
items in an store where the i<sup>th</sup> item has a price of prices[i]
and a profit of profits[i]
.
You have to select three items with the following condition:
prices[i] < prices[j] < prices[k]
where i < j < k
.profits[i] + profits[j] + profits[k]
.Return the maximum possible profit from this selection. If it's not possible to select three items that satisfy these conditions, return -1
.
[3, 1, 4, 6, 2]
, profits = [5, 2, 8, 10, 3]
23
(3, 4, 6)
with indices 0, 2, 3
. The corresponding profits are 5 + 8 + 10 = 23
.[2, 7, 1, 5, 8, 10]
, profits = [3, 9, 1, 4, 7, 6]
22
(7, 8, 10)
with indices 1, 4, 5
. The corresponding profits are 9 + 7 + 6 = 22
.[9, 8, 7, 6, 5]
, profits = [10, 9, 8, 7, 6]
-1
Constraints:
To solve this problem, the approach leverages the Binary Indexed Tree (BIT) to efficiently track and query the maximum profits that can be obtained from items with increasing prices. The idea is to calculate the maximum profit for a valid triplet of items, where the prices strictly increase. The BIT helps in maintaining and retrieving the maximum profit seen so far as we traverse the list of prices twice—once from left to right and once from right to left. The solution involves calculating the maximum profit that can be achieved from the left and right segments separately, and then combining them to find the overall maximum profit for any valid triplet.
This approach works efficiently because the BIT allows us to perform both update and query operations in logarithmic time. By maintaining two separate BITs (one for the left traversal and one for the right traversal), we can effectively find the maximum profit for any valid triplet by combining the best profits found during the left and right traversals.
Initialize Variables:
prices
array and store it in maxPrice
. This helps in setting the size of the BIT arrays.bitForMaxLeft
and bitForMaxRight
, both of size maxPrice + 1
. These arrays will be used to store the maximum profit for different price indices during left-to-right and right-to-left traversals.maxLeftProfit
of the same size as the prices
array to store the maximum profit that can be obtained for the left side of each item.Left-to-Right Traversal:
prices
array from left to right.i
, use the getMaxProfit
function to query the BIT bitForMaxLeft
for the maximum profit corresponding to all prices less than prices[i]
.getMaxProfit
: The getMaxProfit
function traverses the BIT from the given price down to 0, finding the maximum profit recorded for any price index less than the current price. This allows us to find the best profit we could have obtained before the current price point, which is essential for calculating valid triplets.maxLeftProfit[i]
. This represents the maximum profit we could have achieved on the left side of prices[i]
.updateBIT
function to update the BIT bitForMaxLeft
with the current prices[i]
and profits[i]
.updateBIT
: The updateBIT
function traverses the BIT from the current price index upwards, ensuring that the maximum profit is recorded at every index touched by the current price. This operation makes sure that any future queries for maximum profit will consider this price's profit as a potential maximum.Right-to-Left Traversal:
maxTotalProfit
to -1
, which will store the maximum profit for any valid triplet found.prices
array from right to left.i
, adjust the price to adjustedPrice = maxPrice - prices[i] + 1
to handle the reverse traversal in the BIT.maxPrice - prices[i] + 1
, we effectively "mirror" the index so that the BIT, which is designed to handle increasing indices naturally, can now handle decreasing price sequences properly during the reverse traversal. This trick allows the same BIT structure to be used in reverse order.bitForMaxRight
for the maximum profit corresponding to all prices greater than prices[i]
.maxLeftProfit[i]
and the profit found from the right traversal are greater than 0, update maxTotalProfit
to the sum of maxLeftProfit[i]
, profits[i]
, and the right profit.bitForMaxRight
with the adjusted price and the current profit.Return Result:
maxTotalProfit
, which holds the maximum profit for any valid triplet or -1
if no valid triplet was found.Input: prices = [3, 1, 4, 6, 2]
, profits = [5, 2, 8, 10, 3]
prices
array.
maxPrice = 6
bitForMaxLeft = [0, 0, 0, 0, 0, 0, 0]
bitForMaxRight = [0, 0, 0, 0, 0, 0, 0]
maxLeftProfit = [0, 0, 0, 0, 0]
maxTotalProfit = -1
Step 1 (i = 0, prices[0] = 3):
getMaxProfit(bitForMaxLeft, 2)
returns 0
(no valid price less than 3).maxLeftProfit[0] = 0
updateBIT(bitForMaxLeft, 3, 5)
i = 3
, update bitForMaxLeft[3] = max(0, 5) = 5
.i = 4
(since i = i + (i & -i)
), update bitForMaxLeft[4] = max(0, 5) = 5
.i = 8
which is out of bounds.bitForMaxLeft = [0, 0, 0, 5, 5, 0, 0]
maxLeftProfit = [0, 0, 0, 0, 0]
Step 2 (i = 1, prices[1] = 1):
getMaxProfit(bitForMaxLeft, 0)
returns 0
(no valid price less than 1).maxLeftProfit[1] = 0
updateBIT(bitForMaxLeft, 1, 2)
i = 1
, update bitForMaxLeft[1] = max(0, 2) = 2
.i = 2
, update bitForMaxLeft[2] = max(0, 2) = 2
.i = 4
, update bitForMaxLeft[4] = max(5, 2) = 5
(no change).i = 8
which is out of bounds.bitForMaxLeft = [0, 2, 2, 5, 5, 0, 0]
maxLeftProfit = [0, 0, 0, 0, 0]
Step 3 (i = 2, prices[2] = 4):
getMaxProfit(bitForMaxLeft, 3)
returns 5
(best profit from price 3).maxLeftProfit[2] = 5
updateBIT(bitForMaxLeft, 4, 8)
i = 4
, update bitForMaxLeft[4] = max(5, 8) = 8
.i = 8
which is out of bounds.bitForMaxLeft = [0, 2, 2, 5, 8, 0, 0]
maxLeftProfit = [0, 0, 5, 0, 0]
Step 4 (i = 3, prices[3] = 6):
getMaxProfit(bitForMaxLeft, 5)
returns 8
(best profit from price 4).maxLeftProfit[3] = 8
updateBIT(bitForMaxLeft, 6, 10)
i = 6
, update bitForMaxLeft[6] = max(0, 10) = 10
.i = 8
which is out of bounds.bitForMaxLeft = [0, 2, 2, 5, 8, 0, 10]
maxLeftProfit = [0, 0, 5, 8, 0]
Step 5 (i = 4, prices[4] = 2):
getMaxProfit(bitForMaxLeft, 1)
returns 2
(best profit from price 1).maxLeftProfit[4] = 2
updateBIT(bitForMaxLeft, 2, 3)
i = 2
, update bitForMaxLeft[2] = max(2, 3) = 3
.i = 4
, update bitForMaxLeft[4] = max(8, 3) = 8
(no change).i = 8
which is out of bounds.bitForMaxLeft = [0, 2, 3, 5, 8, 0, 10]
maxLeftProfit = [0, 0, 5, 8, 2]
Step 1 (i = 4, prices[4] = 2):
adjustedPrice = 6 - 2 + 1 = 5
getMaxProfit(bitForMaxRight, 4)
returns 0
(no valid price greater than 2).updateBIT(bitForMaxRight, 5, 3)
i = 5
, update bitForMaxRight[5] = max(0, 3) = 3
.i = 6
which is out of bounds.bitForMaxRight = [0, 0, 0, 0, 0, 3, 0]
maxTotalProfit = -1
(no update)Step 2 (i = 3, prices[3] = 6):
adjustedPrice = 6 - 6 + 1 = 1
getMaxProfit(bitForMaxRight, 0)
returns 0
(no valid price greater than 6).updateBIT(bitForMaxRight, 1, 10)
i = 1
, update bitForMaxRight[1] = max(0, 10) = 10
.i = 2
, update bitForMaxRight[2] = max(0, 10) = 10
.i = 4
, update bitForMaxRight[4] = max(0, 10) = 10
.i = 8
which is out of bounds.bitForMaxRight = [0, 10, 10, 0, 10, 3, 0]
maxTotalProfit = -1
(no update)Step 3 (i = 2, prices[2] = 4):
adjustedPrice = 6 - 4 + 1 = 3
getMaxProfit(bitForMaxRight, 2)
returns 10
(best profit from price 6).maxTotalProfit = max(-1, 5 + 8 + 10) = 23
updateBIT(bitForMaxRight, 3, 8)
i = 3
, update bitForMaxRight[3] = max(0, 8) = 8
.i = 4
, update bitForMaxRight[4] = max(10, 8) = 10
(no change).i = 8
which is out of bounds.bitForMaxRight = [0, 10, 10, 8, 10, 3, 0]
maxTotalProfit = 23
Step 4 (i = 1, prices[1] = 1):
adjustedPrice = 6 - 1 + 1 = 6
getMaxProfit(bitForMaxRight, 5)
returns 3
(best profit from price 2).maxTotalProfit = max(23, 0 + 2 + 3) = 23
(no change)updateBIT(bitForMaxRight, 6, 2)
i = 6
, update bitForMaxRight[6] = max(0, 2) = 2
.i = 8
which is out of bounds.bitForMaxRight = [0, 10, 10, 8, 10, 3, 2]
maxTotalProfit = 23
Step 5 (i = 0, prices[0] = 3):
adjustedPrice = 6 - 3 + 1 = 4
getMaxProfit(bitForMaxRight, 3)
returns 8
(best profit from price 4).maxLeftProfit[0] = 0
, which is not valid.23
, so return 23
.updateBIT
and getMaxProfit
.updateBIT
operation takes O(\log(\text{maxPrice})) time, where maxPrice
is the maximum value in the prices
array.getMaxProfit
operation also takes O(\log(\text{maxPrice})) time.prices
array twice, each time performing these operations. Therefore, the overall time complexity is O(n\log(\text{maxPrice})), where n
is the length of the prices
array.bitForMaxLeft
and bitForMaxRight
), which have a size of maxPrice + 1
.n
is used for storing maxLeftProfit
......
.....
.....