LEETCODE 1423. Maximum Points You Can Obtain from Cards 解题思路分析

题目大意:

可获得的最大点数

几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 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.

本网站文章均为原创内容,并可随意转载,但请标明本文链接
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: http://leetcode.jp/leetcode-1423-maximum-points-you-can-obtain-from-cards-解题思路分析/
此条目发表在leetcode分类目录,贴了, , , 标签。将固定链接加入收藏夹。

发表评论

您的电子邮箱地址不会被公开。