I came across this question on Leetcode. The question description is as follows:
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.
Return the maximum score you can obtain.
Sample testcases
cardPoints = [1,2,3,4,5,6,1], k = 3 => Output is 12 cardPoints = [2,2,2], k = 2 => Output is 4 cardPoints = [9,7,7,9,7,7,9], k = 7 => Output is 55 cardPoints = [1,1000,1], k = 1 => Output is 1
After looking at the discussion forums, I realized that this could be converted into a sliding window problem where we have to find the smallest subarray sum of length len(cardPoints) - k
.
While I do understand this,
The initial method I tried was brute-force recursive and using dynamic programming to cache intermediate results. Despite this, it still results in a timeout. Is there any other optimization I can make to make my code run faster using this approach?
class Solution {
public:
int maxScoreUtil(int left, int right,vector<int>& cardPoints, int k,vector<vector<int>>& dp){
if(k == 0 || left == cardPoints.size() || right < 0)
return 0;
if(dp[left][right] != -1)
return dp[left][right];
int val_1 = maxScoreUtil(left+1,right,cardPoints,k-1,dp) + cardPoints[left];
int val_2 = maxScoreUtil(left,right-1,cardPoints,k-1,dp) + cardPoints[right];
return dp[left][right] = max(val_1,val_2);
}
int maxScore(vector<int>& cardPoints, int k) {
int n = cardPoints.size();
vector<vector<int>> dp(n+1, vector<int>(n+1, -1));
return maxScoreUtil(0,n-1,cardPoints,k,dp);
}
};I
Before using DP => 16/40 test cases passed followed by TLE
After using DP => 31/40 test cases passed followed by TLE