题目大意:
可获得的最大点数
几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。
示例 1:
输入:cardPoints = [1,2,3,4,5,6,1], k = 3 输出:12 解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。
示例 2:
输入:cardPoints = [2,2,2], k = 2 输出:4 解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。
示例 3:
输入:cardPoints = [9,7,7,9,7,7,9], k = 7 输出:55 解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。
示例 4:
输入:cardPoints = [1,1000,1], k = 1 输出:1 解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 。
示例 5:
输入:cardPoints = [1,79,80,1,1,1,200,1], k = 3 输出:202
提示:
- 1 <= cardPoints.length <= 10^5
- 1 <= cardPoints[i] <= 10^4
- 1 <= k <= cardPoints.length
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1423
解题思路分析:
这道题开始打算使用DP或者递归来解题。我们定义左右两个指针left,right,初始时分别指向数组的首尾两个位置。递归时,我们可以选择左指针的牌cardPoints[left],然后递归到子问题求解。递归时,左指针加一,右指针不变,k值减一,这样cardPoints[left]加上递归子问题的值就能得到一个解Res1。另外我们也可以选择右指针的牌cardPoints[right],然后递归到子问题求解。递归时,左指针不变,右指针减一,k值减一,这样cardPoints[right]加上递归子问题的值就能得到另一个解Res2。Res1与Res2的最大值为当前递归函数的返回值。当k值为0时结束递归返回0。
看似完美的解决方案,但是在为递归函数加记忆数组时,需要三个变量:左指针位置,右指针位置以及k值,从而需要建立三维记忆数组,即是优化至二维数组(舍弃左右指针或者k的其中一个,因为确定任何两个变量,都能推算出第三个变量),依旧空间复杂度过高O(k*Length),从而放弃递归加记忆数组的算法。
实际上本题并没有那么复杂,因为每次只能从数组的两端取一张卡牌,因此在K张卡牌全部取完之后,肯定是在数组的左端取了连续的m张卡牌,同时在数组的右端取了连续的n张卡牌,其中m+n=k。因此我们初始时,可以另m等于k,n等于0,并且计算出当前这k张卡牌的总和。然后循环,每一步为m减一,n加一,并更新当前的总和,同时更新全局最大的总和。直到循环至m等于0,n等于k为止。最大的总和即是返回值。
实现代码:
public int maxScore(int[] cardPoints, int k) { int score=0; // 前k张牌的总和 for(int i=0;i<k;i++){ score+=cardPoints[i]; } // 初始时,左边选k张牌,右边选0张牌 int leftIndex=k-1, rightIndex=cardPoints.length; // 最大得分 int max=score; // 循环,不断从左边减少一张牌,右边增加一张牌 while(leftIndex>=0){ // 减去左指针这张牌的点数 score-=cardPoints[leftIndex]; // 左指针减一 leftIndex--; // 右指针减一 rightIndex--; // 加上右指针这张牌的点数 score+=cardPoints[rightIndex]; // 更新最大点数和 max=Math.max(max, score); } return max; }
本题解法执行时间为1ms。
Runtime: 1 ms, faster than 100.00% of Java online submissions for Maximum Points You Can Obtain from Cards.
Memory Usage: 48.2 MB, less than 100.00% of Java online submissions for Maximum Points You Can Obtain from Cards.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/leetcode-1423-maximum-points-you-can-obtain-from-cards-解题思路分析/