Maximum Points You Can Obtain from Cards

Updated on 09 June, 2025
Maximum Points You Can Obtain from Cards header image

Problem Statement

In this problem, we're given an array cardPoints where each element represents the number of points that each card in a row offers. We are required to select exactly k cards to maximize our score, but with a specific constraint: we can only take cards from either the beginning or the end of the row. The task is to determine the maximum score possible by choosing the best combination of k cards from these two ends.

Examples

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 <= 105
  • 1 <= cardPoints[i] <= 104
  • 1 <= k <= cardPoints.length

Approach and Intuition

To understand the approach to solve this problem, let’s break down the underlying strategy using the examples provided:

Example 1 Analysis:

  • Input: cardPoints = [1,2,3,4,5,6,1], k = 3
  • If we look closely, selecting the last three cards (1, 6, 5) gives us the maximum points (12). It becomes evident that the problem revolves around optimizing which cards we are choosing while still sticking to the game rule of only picking from either end.

Example 2 Analysis:

  • Input: cardPoints = [2,2,2], k = 2
  • Here, it doesn't matter which cards we pick as they all give the same points, aligning with the max score of 4.

Example 3 Analysis:

  • Input: cardPoints = [9,7,7,9,7,7,9], k = 7
  • As we need to pick all the cards, this directly results in the total sum of all cards in the row, showcasing a situation where the bounds (k equal to the length of cardPoints) simplifies the problem.

Observations:

  1. One end might not necessarily hold the overall maximum scoring potential. It's essential to consider combinations of both ends.
  2. Utilizing a strategy where you sum the total points and subtract the sum of the points of the cards we've decided not to take could lead to an efficient solution.

Optimized Strategy:

  • This problem can effectively be transformed into finding the minimum sum of a subarray of length cardPoints.length - k (i.e., the cards not taken), and subtract that from the total sum of cardPoints.
  • By minimizing the sum of the cards not taken, we maximize the sum of the cards taken from either end.
  • This involves:
    • Calculating the total sum of cardPoints.
    • Then, finding the smallest possible sum of a consecutive subarray with length cardPoints.length - k.
    • Subsequently, the maximum score is given by subtracting this smallest sub-array sum from the total sum of the array.

By understanding and leveraging these patterns and transformations, we can optimize our approach to solve the problem efficiently.

Solutions

  • C++
  • Java
cpp
class Solution {
public:
    int maximumScore(vector<int>& cards, int k) {
        int leftIndex = 0;
        int currentSum = 0;
        int cardsCount = cards.size();
        int lengthToConsider = cardsCount - k;
        int minimumSum;
        int aggregateSum = 0;

        // Sum of all cards
        for (int cardValue : cards) {
            aggregateSum += cardValue;
        }

        minimumSum = aggregateSum;

        if (k == cardsCount) {
            return aggregateSum;
        }

        for (int idx = 0; idx < cardsCount; idx++) {
            currentSum += cards[idx];
            int currentLength = idx - leftIndex + 1;
            
            if (currentLength == lengthToConsider) {
                minimumSum = min(minimumSum, currentSum);
                currentSum -= cards[leftIndex++];
            }
        }
        return aggregateSum - minimumSum;
    }
};

The problem requires determining the maximum points you can obtain by picking cards from either end using C++. The approach involves a sliding window technique combined with prefix sum logic.

  • Initialize pointers and variables to manage your current subset of cards and the sum of their values.
  • Calculate the total sum of all card values.
  • If the subset k is equal to the total number of cards, simply return the total, as this means all cards are taken.
  • Iterate through the card values, expanding the window to the desired length, which is notably the difference between the total card count and k.
  • Keep track of the minimum sum for any valid window of cardsCount - k.
  • Deduct this minimum window sum from the total sum of all cards to derive the maximum achievable points.

The implementation successfully provides an efficient way to leverage both aggregate summation and concise window adjustments to determine the maximum score from the given card selection constraints. Use this understanding to handle and manipulate arrays efficiently in similar problems.

java
class Solution {
    public int calculateMaxScore(int[] points, int k) {
        int start = 0;
        int currentScore = 0;
        int length = points.length;
        int subarraySize = length - k;
        int minSubarrayScore;
        int totalPoints = 0;

        // Summing up all elements in the array for the total score.
        for (int point : points) {
            totalPoints += point;
        }

        minSubarrayScore = totalPoints;

        if (k == length) {
             return totalPoints;
        }

        for (int i = 0; i < length; i++) {
            currentScore += points[i];
            int currentLength = i - start + 1;
            // Check if the subarray of required length exists.
            if (currentLength == subarraySize) {
                minSubarrayScore = Math.min(minSubarrayScore, currentScore);
                currentScore -= points[start++];
            }
        }
        return totalPoints - minSubarrayScore;
    }
}

In the provided Java solution for the problem of calculating the maximum points obtainable from a card game, the approach revolves around using a sliding window technique to minimize the sum of a subarray, ultimately maximizing the sum of the remaining elements. Here’s an insightful breakdown of how the code achieves this:

  1. Initialize the essential variables including start index for the sliding window, currentScore to track the score of the current window, length as the total number of cards, and subarraySize that represents the size of the subarray which is the complement of desired cards, k.
  2. Compute the totalPoints by accumulating all points from the card array.
  3. Set minSubarrayScore as totalPoints initially for a baseline to find minimum.
  4. If k equals the length of the card array, simply return totalPoints as removing no cards gives the maximum score.
  5. Utilize a loop to traverse the card points:
    • Add the points of the card at the current index to currentScore.
    • Maintain the window size matching subarraySize: Check if the window has reached the desired subarraySize and update minSubarrayScore to be the minimum of its current value or currentScore.
    • Slide the window by subtracting the point at the start index from currentScore and incrementing the start index.
  6. After the loop, return the difference between totalPoints and minSubarrayScore which gives the maximum points you can obtain.

This solution effectively finds the least valuable subset of cards to remove (i.e., subarray with minimal points) ensuring the most points from the remaining cards in the hand.

Comments

No comments yet.