Skip to main content

Sliding Window

Maximum Points You Can Obtain from Cards Solution In C++/Java/Python/JS

Problem Description

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

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.

Input: cardPoints = [2,2,2], k = 2
Output: 4
Explanation: Regardless of which two cards you take, your score will always be 4.

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
💡
Try Solving "Maximum Points You Can Obtain from Cards" Yourself First !!

Figuring out "Maximum Points You Can Obtain from Cards" can be solved using different approaches. We will first figure out the most intuitive approach and move to the optimal approach if exists. Let's sit with a pen and paper and figure out the algorithm !!

Optimal Approach

Intuition

Imagine we’re sitting at a table, and laid out in front of us is a long row of cards. Each card has a number written on it — and that number? That’s how many points we’ll earn if we take that card.

But — there’s a twist.
We can’t just grab whatever card we like.

Here’s the Rule:
We’re allowed to take exactly k cards — no more, no less.
But we can only pick from either the start (left) or the end (right) of the row.
Not from the middle. Not randomly.
One at a time. From either end.

That’s right — we might decide to:

  • Take all k cards from the front,
  • Take all from the back,
  • Or mix it up — like 2 from the front, 1 from the back (if k = 3), or maybe 1 from the front, 4 from the back (if k = 5), etc.

And once we’ve picked k cards?

Our goal is simple:
Get the maximum possible total score from those cards.

Let’s Work with a Fresh Example

Suppose we’re given:

cardPoints = [10, 20, 15, 5, 25, 10, 40], k = 3

We need to pick 3 cards, only from the ends, to get the maximum score possible.

Let’s just try out a few possibilities manually, like we would on paper:

  • Take all 3 from the front:
    10 + 20 + 15 = 45
  • Take 2 from front, 1 from back:
    10 + 20 + 40 = 70
  • Take 1 from front, 2 from back:
    10 + 10 + 40 = 60
  • Take all 3 from the back:
    40 + 10 + 25 = 75, Best so far!

Looks like picking all 3 cards from the back gives us the highest total — 75.

Not bad! This small test run helps us understand the mechanics of the problem.

Here’s Where It Gets Interesting…

So far, things look easy, right?
We just try a few combinations, add them up, and take the maximum.

But here’s the twist:

What happens when our input is huge?

Imagine: cardPoints.length = 100,000, k = 50,000

Suddenly, trying out every combination like we just did becomes… a serious problem.

Because now:

  • We’d be testing 50,001 different ways to split the picks (from all-front to all-back),
  • And each combination would involve summing up 50,000 numbers

That’s a lot of work.

And if we use nested loops or brute-force techniques to test every single front–back split?

We’ll end up doing billions of operations. Literally.

That’s not just slow — that’s completely impractical on any real system.

So What’s Our Real Challenge?

The real challenge isn’t understanding what the question asks.
It’s figuring out how to solve it smartly.

We need a solution that:

  • Works fast even when k is very large,
  • Doesn’t waste time recomputing the same things again and again,
  • And still guarantees the maximum possible score.

So the question we should be asking isn’t:

“How can I test every possible combination?”

Instead, we should ask:

“Is there a pattern or structure in how these combinations change… so we can avoid recomputation?”

Should We Try Every Possible Way?

Let’s now ask the question that might pop into anyone’s mind at this point:

“Well… why don’t we just try every possible combination of k picks? Wouldn’t that work?”

It seems innocent enough. After all, it worked perfectly in our small example where k = 3, right?

Let’s zoom in and test this idea more carefully.

So... What Are All the Valid Ways to Pick k Cards?

We know the rule:
You can only take cards from the front (left) or the back (right) — one at a time.

And we have to pick exactly k cards.

So what kind of combinations are actually allowed?

Let’s break it down.

If k = 3, the only valid ways to split your picks are:

Picks from Front

Picks from Back

Total Cards

3

0

Valid

2

1

Valid

1

2

Valid

0

3

Valid

So we have exactly k + 1 = 4 possible combinations.

Seems totally reasonable.

If k = 4, we’ll have 5 combinations:

  • 4 front, 0 back
  • 3 front, 1 back
  • 2 front, 2 back
  • 1 front, 3 back
  • 0 front, 4 back

Each of those combinations is a different way to split k picks between the two ends.

So naturally, we might say:

“Let’s loop from i = 0 to k,
For each i, take i cards from the front and k - i from the back,
Add the points, and track the best total!”

Sounds like a plan. Let’s try it.

Let’s Write Out a Simple Simulation

Let’s reuse our earlier input:

cardPoints = [10, 20, 15, 5, 25, 10, 40], k = 3

Try all valid front/back splits:

  • 3 front → 10 + 20 + 15 = 45
  • 2 front, 1 back → 10 + 20 + 40 = 70
  • 1 front, 2 back → 10 + 10 + 40 = 60
  • 3 back → 25 + 10 + 40 = 75

Yep! That brute-force method worked just fine here.

But wait…

What Happens When k Gets Big?

Let’s now revisit the scary case we talked about at the end of Part 1:

cardPoints.length = 100,000

k = 50,000

That means:

  • There are 50,001 possible front/back combinations (from 0 front to 50,000 front).
  • And for each combination, we’re summing up 50,000 numbers.

Let’s do the math:

50,001 combinations × 50,000 elements per sum = 2,500,050,000 operations

That’s over 2.5 billion additions just to brute-force through the options!

Even if each addition took just 1 microsecond, that’s:

2.5 billion microseconds = 2,500 seconds ≈ 40+ minutes

That’s simply too slow for most coding problems — especially when you’re on a timer or writing real-world software.

So Wait… Are We Repeating Work?

Let’s step back and really think about what changes between each combination.

Say our first pick is the 3 front cards:

10 + 20 + 15 = 45

Then we try 2 from the front, 1 from the back:

10 + 20 + 40 = ?

Hold on — we already had 10 + 20 + 15.

Now we just:

  • Remove 15 (the last card from the front)
  • Add 40 (the new card from the back)

Instead of redoing the whole sum…

Why not just adjust the previous total?

newTotal = oldTotal - frontRemoved + backAdded

That’s just two operations per step instead of 3 or 50,000.

That’s way more efficient!

Let’s Try That With a Small Example

Say again:

cardPoints = [10, 20, 15, 5, 25, 10, 40], k = 3

Step 1:

Start with first 3 front cards:
leftSum = 10 + 20 + 15 = 45
rightSum = 0
max = 45

Step 2:
Remove 15 from left, add 40 from right
leftSum = 30 
rightSum = 40 
total = 70 
max = 70

Step 3:
Remove 20, add 10
leftSum = 10 
rightSum = 50 
total = 60 
max = 70 (still)

Step 4:
Remove 10, add 25
leftSum = 0 
rightSum = 75 
total = 75

We reach the maximum. No need to re-add everything every time. Just a tiny update at each step.

Well wrapped up! Now, if we take a step back and really look at what we did — we weren’t guessing, and we weren’t recalculating everything from scratch. Instead, we carefully slid a window across all possible front–back combinations, adjusting the total by just one number at a time.

And that kind of thinking?
That’s the heart of a sliding window strategy.

We didn’t brute-force all options — we simply reused previous work, kept the window moving, and let the math guide us toward the best score.
Simple, efficient, and powerful.

Let's now see how our algorithm looks!

Maximum Points You Can Obtain from Cards Algorithm

  1. We begin by choosing all k cards from the start (left side) of the array. This gives us an initial maximum score to work with.
  2. We prepare to explore other combinations by gradually removing cards from the left and adding from the right, simulating every valid split of k cards.
  3. We use two accumulators:
    • leftSum to track the total of cards chosen from the start.
    • rightSum to track the total of cards chosen from the end.
  4. We maintain a running maximum score by checking each new combination (leftSum + rightSum) as we slide the selection.
  5. We return the highest score obtained from all combinations.

Approach

  • Initialize Sum of First k Elements: leftSum = sum of first k elements of cardPoints.
  • Initialize Variables: rightSum = 0, rightIndex = cardPoints.length, ans = leftSum.
  • Use a Reverse Loop Over the Left Side:
    Iterate leftIndex from k - 1 to 0:
    • Subtract cardPoints[leftIndex] from leftSum (removing from the left).
    • Decrement rightIndex and add cardPoints[rightIndex] to rightSum (adding from the right).
    • Update ans as the maximum of ans and leftSum + rightSum.
  • Return Final Answer: Return ans as the maximum score after considering all combinations.

Dry-Run

Input: cardPoints = [4, 2, 10, 1, 3, 6, 8], k = 4
Output: 24

We need to pick 4 cards, either from the start or end (or mix of both), and maximize the sum.

Explanation
Let’s simulate this step-by-step using a sliding window strategy, starting by taking all cards from the front and gradually shifting picks from the front to the back.

Step 0: Take all 4 from the front
[4, 2, 10, 1] ← taken from the left
Sum = 4 + 2 + 10 + 1 = 17
maxScore = 17

Step 1: Take 3 from front, 1 from back
Remove 1 (from left), add 8 (from right)
[4, 2, 10] + [8]
Sum = 4 + 2 + 10 + 8 = 24
maxScore = max(17, 24) = 24

Step 2: Take 2 from front, 2 from back
Remove 10 (from left), add 6 (from right)
[4, 2] + [6, 8]
Sum = 4 + 2 + 6 + 8 = 20
maxScore = max(24, 20) = 24

Step 3: Take 1 from front, 3 from back
Remove 2 (from left), add 3 (from right)
[4] + [3, 6, 8]
Sum = 4 + 3 + 6 + 8 = 21
maxScore = max(24, 21) = 24

Step 4: Take all 4 from the back
Remove 4 (from left), add 1 (from right)
[1, 3, 6, 8] ← taken from the right
Sum = 1 + 3 + 6 + 8 = 18
maxScore = max(24, 18) = 24

Final Answer: The maximum score we can obtain = 24

Maximum Points You Can Obtain from Cards Solution

Now let's checkout the "Maximum Points You Can Obtain from Cards code" in C++, Java, Python and JavaScript.

"Maximum Points You Can Obtain from Cards" Code in all Languages.
1. Maximum Points You Can Obtain from Cards solution in C++ Try on Compiler
class Solution {

public:

    int maxScore(vector<int>& cardPoints, int k) {

        // Get the total number of cards
        int n = cardPoints.size();

        // Sum of the first k cards from the left
        int leftSum = 0;

        for (int i = 0; i < k; i++) {

            leftSum += cardPoints[i];
        }

        // Initialize rightSum and pointers for right side
        int rightSum = 0;
        int rightIndex = n;

        // Initialize answer with full left pick
        int ans = leftSum;

        for (int leftIndex = k - 1; leftIndex >= 0; leftIndex--) {

            leftSum -= cardPoints[leftIndex];
            rightIndex--;
            rightSum += cardPoints[rightIndex];
            ans = max(ans, leftSum + rightSum);
        }

        return ans;
    }
};

2. Maximum Points You Can Obtain from Cards Solution in Java Try on Compiler
class Solution {

    public int maxScore(int[] cardPoints, int k) {

        // Get total number of cards
        int n = cardPoints.length;

        // Sum of the first k cards from the left
        int leftSum = 0;

        for (int i = 0; i < k; i++) {

            leftSum += cardPoints[i];
        }

        // Initialize rightSum and pointer for right side
        int rightSum = 0;
        int rightIndex = n;

        // Initialize answer with full left pick
        int ans = leftSum;

        for (int leftIndex = k - 1; leftIndex >= 0; leftIndex--) {

            leftSum -= cardPoints[leftIndex];
            rightIndex--;
            rightSum += cardPoints[rightIndex];
            ans = Math.max(ans, leftSum + rightSum);
        }

        return ans;
    }
}

3. Maximum Points You Can Obtain from Cards Solution in Python Try on Compiler
class Solution:

    def maxScore(self, cardPoints: List[int], k: int) -> int:

        # Get total number of cards
        n = len(cardPoints)

        # Sum of the first k cards from the left
        leftSum = sum(cardPoints[:k])

        # Initialize rightSum and pointer for right side
        rightSum = 0
        rightIndex = n

        # Initialize answer with full left pick
        ans = leftSum

        for leftIndex in range(k - 1, -1, -1):

            leftSum -= cardPoints[leftIndex]
            rightIndex -= 1
            rightSum += cardPoints[rightIndex]
            ans = max(ans, leftSum + rightSum)

        return ans

4. Maximum Points You Can Obtain from Cards solution in JavaScript Try on Compiler
/**
 * @param {number[]} cardPoints
 * @param {number} k
 * @return {number}
 */
var maxScore = function(cardPoints, k) {

    // Get total number of cards
    const n = cardPoints.length;

    // Sum of the first k cards from the left
    let leftSum = 0;

    for (let i = 0; i < k; i++) {

        leftSum += cardPoints[i];
    }

    // Initialize rightSum and pointer for right side
    let rightSum = 0;
    let rightIndex = n;

    // Initialize answer with full left pick
    let ans = leftSum;

    for (let leftIndex = k - 1; leftIndex >= 0; leftIndex--) {

        leftSum -= cardPoints[leftIndex];
        rightIndex--;
        rightSum += cardPoints[rightIndex];
        ans = Math.max(ans, leftSum + rightSum);
    }

    return ans;
};

Maximum Points You Can Obtain from Cards Complexity Analysis

Time Complexity: O(k)

The Maximum Points You Can Obtain from Cards algorithm involves two key operations:

  1. Calculating the initial sum of the first k cards (left side):
    We compute the sum of the first k elements in a single pass.
    This operation takes O(k) time.
  2. Sliding the window by shifting picks from front to back:
    We simulate each possible combination by removing one card from the front and adding one from the back.
    For each shift, we update the current sum in constant time.
    This loop runs k times, so it also takes O(k) time.
  3. Returning the maximum score:
    A constant-time operation O(1).

Thus, the overall time complexity is:
O(k) + O(k) + O(1) = O(k),
where k is the number of cards to pick.

Space Complexity: O(1)

Auxiliary Space Complexity:
Auxiliary space refers to the extra space required by the algorithm excluding the input.

  • Sum variables:
    We use variables like leftSum, rightSum, maxScore, and a few loop counters. These occupy constant space O(1).
  • No additional data structures:
    The algorithm does not use any dynamic data structures (like arrays, lists, or maps) that scale with input size.

Thus, the auxiliary space complexity is O(1).

Total Space Complexity:

  • Input array:
    The input array cardPoints occupies O(n) space, where n is the length of the array.
  • Extra space:
    All extra space (used for accumulators and loop variables) is O(1) as discussed.

Hence, the total space complexity is: O(n + 1) = O(n).


Similar Problems

You are given two 0-indexed integer arrays nums and multipliers of size n and m respectively, where n >= m.

You begin with a score of 0. You want to perform exactly m operations. On the ith operation (0-indexed) you will:

  • Choose one integer x from either the start or the end of the array nums.
  • Add multipliers[i] * x to your score.
    • Note that multipliers[0] corresponds to the first operation, multipliers[1] to the second operation, and so on.
  • Remove x from nums.

Return the maximum score after performing operations.

You are given a 0-indexed array of distinct integers nums.

There is an element in nums that has the lowest value and an element that has the highest value. We call them the minimum and maximum respectively. Your goal is to remove both these elements from the array.

deletion is defined as either removing an element from the front of the array or removing an element from the back of the array.

Return the minimum number of deletions it would take to remove both the minimum and maximum element from the array.