LeetCode: 5393. 可获得的最大点数 C语言版
题目:
几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。
示例 1:
输入:cardPoints = [1,2,3,4,5,6,1], k = 3
输出:12
解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。
解:
其实这个题的解法还是很多的,我一开始想的是直接i从0循环到k,然后在循环里面分别写两个循环,一个是左边取i个数相加,一个是右边取k-i个数相加。然后给一个max,在这些循环中找到最大值,但是这样的时间复杂度就很大,妥妥的O(K^2),所以运行后时间超时。然后改进之后选择这么写。
int maxScore(int* cardPoints, int cardPointsSize, int k)
{
int max = 0;
int i , j , x = 0;
//存储左边和右边的值
int left[100000] = {0} , right[100000] = {0};
/*当取的k与卡片数相同时,直接返回所有卡牌之和*/
if(cardPointsSize <= k)
{
for(i = 0 ; i < cardPointsSize ; i++ )
max = max + cardPoints[i];
return max;
}
/*当只取一次卡牌时,返回左或右的最大值*/
if(k == 1)
return cardPoints[0] > cardPoints[cardPointsSize - 1] ? cardPoints[0] : cardPoints[cardPointsSize - 1];
j = 1;
/*从左边取0到k次的和存入数组*/
for(i = 0 ; i <= k ; i++)
left[j++] = left[i] + cardPoints[i];
i = 1;
/*从右边取0到k次的和存入数组*/
for(j = cardPointsSize - 1 ; j > cardPointsSize - 1 - k ; j--)
right[i++] = right[x++] + cardPoints[j];
/*从左边取i次,右边取k-i次,返回最大值*/
for( i = 0 ; i <= k ; i++)
max = left[i] + right[k-i] > max ? left[i] + right[k-i] : max;
return max;
}