zoukankan      html  css  js  c++  java
  • [LeetCode] 1423. Maximum Points You Can Obtain from Cards

    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.

    Given the integer array cardPoints and the integer k, return the maximum score you can obtain.

    Example 1:

    Input: cardPoints = [1,2,3,4,5,6,1], k = 3
    Output: 12
    Explanation: After the first step, your score will always be 1. However, choosing the rightmost card first will maximize your total score. 
    The optimal strategy is to take the three cards on the right, giving a final score of 1 + 6 + 5 = 12.

    Example 2:

    Input: cardPoints = [2,2,2], k = 2
    Output: 4
    Explanation: Regardless of which two cards you take, your score will always be 4.
    

    Example 3:

    Input: cardPoints = [9,7,7,9,7,7,9], k = 7
    Output: 55
    Explanation: You have to take all the cards. Your score is the sum of points of all cards.
    

    Example 4:

    Input: cardPoints = [1,1000,1], k = 1
    Output: 1
    Explanation: You cannot take the card in the middle. Your best score is 1. 
    

    Example 5:

    Input: cardPoints = [1,79,80,1,1,1,200,1], k = 3
    Output: 202

    Constraints:

    • 1 <= cardPoints.length <= 10^5
    • 1 <= cardPoints[i] <= 10^4
    • 1 <= k <= cardPoints.length

    可获得的最大点数。

    几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。

    每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。

    你的点数就是你拿到手中的所有卡牌的点数之和。

    给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/maximum-points-you-can-obtain-from-cards
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    这道题有两种做法,一种是前缀和 + 滑动窗口,另一种是动态规划,我这里暂时先提供前一种做法。动态规划的思路我自己想清楚了日后再补充。这道题滑动窗口的思路也可以应用到1509题

    这道题同时有一个陷阱:双指针的思路是行不通的。比如题目给的第一个例子,按照题意,如果为了使得拿到的分数更多,选择更多的卡牌,我们不知道要取哪个1,因为我们不知道拿掉1之后,到底左边还是右边会遇到更大的数字。

    题设说的拿掉卡牌的规则是一定要从数组的两端拿,一共拿K张牌。那么如果我们反过来想,假设数组的长度为len,我们创建一个长度为 len - K 的子数组,使得这个子数组的和最小,剩下的部分不就是题目要求的最大的 K 张牌吗?至于具体做法,我们首先求出input数组中前 K 张牌的和,把这个和暂时记为max。然后我们不断地把这个子数组最右边的元素用input数组最右边的元素进行替换,尝试得到一个和最大的子数组。

    跑一个例子,

    Input: cardPoints = [1,79,80,1,1,1,200,1], k = 3
    Output: 202

    K = 3,一开始我们求的前K个元素组成的子数组的和 = 1 + 79 + 80 = 160,然后我们从数组的最右边开始(黄色部分),逐渐开始替换子数组里面最右边的元素(蓝色部分的最右边的元素)。替换过程如下,

    cardPoints = [1,79,80,1,1,1,200,1]
    cardPoints = [1,79,80,1,1,1,200,1]
    cardPoints = [1,79,80,1,1,1,200,1]
    cardPoints = [1,79,80,1,1,1,200,1]
    cardPoints = [1,79,80,1,1,1,200,1]

    最后我们得出的最大的子数组的和 = 1 + 200 + 1 = 202。

    时间O(n)

    空间O(1)

    Java实现

     1 class Solution {
     2     public int maxScore(int[] cardPoints, int k) {
     3         int max = 0;
     4         int sum = 0;
     5         int len = cardPoints.length;
     6         for (int i = 0; i < k; i++) {
     7             sum += cardPoints[i];
     8         }
     9         max = sum;
    10         for (int i = 1; i <= k; i++) {
    11             sum = sum + cardPoints[len - i] - cardPoints[k - i];
    12             max = Math.max(max, sum);
    13         }
    14         return max;
    15     }
    16 }

    相关题目

    1423. Maximum Points You Can Obtain from Cards

    1509. Minimum Difference Between Largest and Smallest Value in Three Moves

    LeetCode 题目总结

  • 相关阅读:
    Graphics竖排打印字体
    VC GetDlgItem
    C# FontStyle
    VC弹出"选择文件"和"选择文件夹"对话框(转)
    VC获取应用程序路径
    SqlServer延时函数
    volatile修饰变量
    外部命令和内部命令
    curl命令简单使用
    close_socket断开连接的方式
  • 原文地址:https://www.cnblogs.com/cnoodle/p/14381833.html
Copyright © 2011-2022 走看看