Maximum Points You Can Obtain from Cards
MedPrompt
There are several cards arranged in a row, and each card has an associated number of points. The points are given in the integer array cardPoints.
In one step, you can take one card from the beginning or from the end of the row. You have to take exactly k cards.
Your score is the sum of the points of the cards you have taken.
Given the integer array cardPoints and the integer k, return the maximum score you can obtain.
Example 1:
Input: cardPoints = [1,2,3,4,5,6,1], k = 3
Output: 12
Explanation: After the first step, your score will always be 1. However, choosing the rightmost card first will maximize your total score. The optimal strategy is to take the three cards on the right, giving a final score of 1 + 6 + 5 = 12.Example 2:
Input: cardPoints = [2,2,2], k = 2
Output: 4
Explanation: Regardless of which two cards you take, your score will always be 4.Example 3:
Input: cardPoints = [9,7,7,9,7,7,9], k = 7
Output: 55
Explanation: You have to take all the cards. Your score is the sum of points of all cards.
Constraints:
1 <= cardPoints.length <= 1051 <= cardPoints[i] <= 1041 <= k <= cardPoints.length
Approaches
3 approaches with complexity analysis and trade-offs.
This approach directly models the problem statement. At each step, we have two choices: take a card from the left end or the right end. We need to make k such choices. A recursive function can explore all possible sequences of choices and find the one that yields the maximum score.
Algorithm
- Define a recursive function
findMaxScore(points, left, right, k). - Base Case: If
k == 0, return 0. - Recursive Step:
scoreLeft = points[left] + findMaxScore(points, left + 1, right, k - 1).scoreRight = points[right] + findMaxScore(points, left, right - 1, k - 1).- Return
max(scoreLeft, scoreRight).
- Initial call:
findMaxScore(cardPoints, 0, n-1, k).
Walkthrough
We define a recursive function, say findMaxScore(points, left, right, k), which calculates the maximum score obtainable from the subarray points[left...right] by taking k more cards.
The base case for the recursion is when k becomes 0, meaning we have taken the required number of cards. In this case, the score to be added is 0, so we return 0.
In the recursive step, we explore the two possible moves:
- Take the card at the
leftindex: The score for this choice ispoints[left]plus the result of the recursive call on the smaller subarraypoints[left + 1...right]withk-1cards to take. - Take the card at the
rightindex: The score for this choice ispoints[right]plus the result of the recursive call on the smaller subarraypoints[left...right - 1]withk-1cards to take. The function returns the maximum of these two scores. The initial call to this function would befindMaxScore(cardPoints, 0, cardPoints.length - 1, k). This method explores a binary tree of choices of depthk, leading to an exponential number of computations.
class Solution { public int maxScore(int[] cardPoints, int k) { return findMaxScore(cardPoints, 0, cardPoints.length - 1, k); } private int findMaxScore(int[] points, int left, int right, int k) { // Base case: no more cards to take if (k == 0) { return 0; } // Option 1: Take the leftmost card int takeLeft = points[left] + findMaxScore(points, left + 1, right, k - 1); // Option 2: Take the rightmost card int takeRight = points[right] + findMaxScore(points, left, right - 1, k - 1); // Return the maximum of the two options return Math.max(takeLeft, takeRight); }}Complexity
Time
O(2^k). The recursion tree has a depth of `k`, and each node branches into two, resulting in `2^k` calls at the last level.
Space
O(k). The depth of the recursion stack can go up to `k`.
Trade-offs
Pros
It's a straightforward translation of the problem's decision-making process.
Simple to conceptualize and implement.
Cons
Extremely inefficient due to its exponential time complexity.
Will result in a 'Time Limit Exceeded' error for all but the smallest values of
k.
Solutions
Solution
/** * @param {number[]} cardPoints * @param {number} k * @return {number} */ var maxScore = function (cardPoints, k) { const n = cardPoints.length; let s = cardPoints.slice(-k).reduce((a, b) => a + b); let ans = s; for (let i = 0; i < k; ++i) { s += cardPoints[i] - cardPoints[n - k + i]; ans = Math.max(ans, s); } return ans; };Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.