【力扣】1423. 可获得的最大点数

以下为力扣官方题解,以及本人代码

题目

几张卡牌排成一行,每张卡牌都有一个对应的点数。点数由整数数组 c a r d P o i n t s cardPoints cardPoints 给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k k k 张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 c a r d P o i n t s cardPoints cardPoints 和整数 k k k,请你返回可以获得的最大点数。

示例1

输入 c a r d P o i n t s = [ 1 , 2 , 3 , 4 , 5 , 6 , 1 ] , k = 3 cardPoints = [1,2,3,4,5,6,1], k = 3 cardPoints=[1,2,3,4,5,6,1],k=3
输出 12 12 12
解释:第一次行动,不管拿哪张牌,你的点数总是 1 1 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 1 + 6 + 5 = 12 1+6+5=12

示例2

输入 c a r d P o i n t s = [ 2 , 2 , 2 ] , k = 2 cardPoints = [2,2,2], k = 2 cardPoints=[2,2,2],k=2
输出 4 4 4
解释:无论你拿起哪两张卡牌,可获得的点数总是 4 4 4

示例3

输入 c a r d P o i n t s = [ 9 , 7 , 7 , 9 , 7 , 7 , 9 ] , k = 7 cardPoints = [9,7,7,9,7,7,9], k = 7 cardPoints=[9,7,7,9,7,7,9],k=7
输出 55 55 55
解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。

示例4

输入 c a r d P o i n t s = [ 1 , 1000 , 1 ] , k = 1 cardPoints = [1,1000,1], k = 1 cardPoints=[1,1000,1],k=1
输出 1 1 1
解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 1 1

示例5

输入 c a r d P o i n t s = [ 1 , 79 , 80 , 1 , 1 , 1 , 200 , 1 ] , k = 3 cardPoints = [1,79,80,1,1,1,200,1], k = 3 cardPoints=[1,79,80,1,1,1,200,1],k=3
输出 202 202 202

提示

  1. 1 < = c a r d P o i n t s . l e n g t h < = 1 0 5 1 <= cardPoints.length <= 10^5 1<=cardPoints.length<=105
  2. 1 < = c a r d P o i n t s [ i ] < = 1 0 4 1 <= cardPoints[i] <= 10^4 1<=cardPoints[i]<=104
  3. 1 < = k < = c a r d P o i n t s . l e n g t h 1 <= k <= cardPoints.length 1<=k<=cardPoints.length

官方题解 滑动窗口

思路

记数组 c a r d P o i n t s cardPoints cardPoints 的长度为 nnn,由于只能从开头和末尾拿 k k k 张卡牌,所以最后剩下的必然是连续的 n − k n-k nk 张卡牌。

我们可以通过求出剩余卡牌点数之和的最小值,来求出拿走卡牌点数之和的最大值。

算法

由于剩余卡牌是连续的,使用一个固定长度为 n − k n-k nk 的滑动窗口对数组 c a r d P o i n t s cardPoints cardPoints 进行遍历,求出滑动窗口最小值,然后用所有卡牌的点数之和减去该最小值,即得到了拿走卡牌点数之和的最大值。

本人代码

class Solution {
    public int maxScore(int[] cardPoints, int k) {
        int n = cardPoints.length;
        int size = n-k;

        int sum = 0;
        for (int i=0; i<size; i++)
            sum += cardPoints[i];

        int minSum = sum;
        for (int i=size; i<n; i++)
        {
            sum = sum + cardPoints[i] - cardPoints[i-size];
            minSum = Math.min(minSum, sum);
        }

        return Arrays.stream(cardPoints).sum()-minSum;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n c a r d P o i n t s cardPoints cardPoints 的长度。
  • 空间复杂度: O ( 1 ) O(1) O(1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨momo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值