移除石子的最大得分

80 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情

问题描述

你正在玩一个单人游戏,面前放置着大小分别为 a​​​​​​、b 和 c​​​​​​ 的 三堆 石子。

每回合你都要从两个 不同的非空堆 中取出一颗石子,并在得分上加 1 分。当存在 两个或更多 的空堆时,游戏停止。

给你三个整数 a 、b 和 c ,返回可以得到的 最大分数 。

示例 1:

输入: a = 2, b = 4, c = 6
输出: 6
解释: 石子起始状态是 (2, 4, 6) ,最优的一组操作是:
- 从第一和第三堆取,石子状态现在是 (1, 4, 5)
- 从第一和第三堆取,石子状态现在是 (0, 4, 4)
- 从第二和第三堆取,石子状态现在是 (0, 3, 3)
- 从第二和第三堆取,石子状态现在是 (0, 2, 2)
- 从第二和第三堆取,石子状态现在是 (0, 1, 1)
- 从第二和第三堆取,石子状态现在是 (0, 0, 0)
总分:6 分 。

示例 2:

输入: a = 4, b = 4, c = 6
输出: 7
解释: 石子起始状态是 (4, 4, 6) ,最优的一组操作是:
- 从第一和第二堆取,石子状态现在是 (3, 3, 6)
- 从第一和第三堆取,石子状态现在是 (2, 3, 5)
- 从第一和第三堆取,石子状态现在是 (1, 3, 4)
- 从第一和第三堆取,石子状态现在是 (0, 3, 3)
- 从第二和第三堆取,石子状态现在是 (0, 2, 2)
- 从第二和第三堆取,石子状态现在是 (0, 1, 1)
- 从第二和第三堆取,石子状态现在是 (0, 0, 0)
总分:7 分 。

示例 3:

输入: a = 1, b = 8, c = 8
输出: 8
解释: 最优的一组操作是连续从第二和第三堆取 8 回合,直到将它们取空。
注意,由于第二和第三堆已经空了,游戏结束,不能继续从第一堆中取石子。

提示:

  • 1 <= a, b, c <= 10^5

思路分析

首先我们要先理解一下题目意思,题目会给我们三个整数a、b、c,分别代表三堆石子堆中的石子数量,我们每次需要从两个不同的非空的石堆中各取出一枚石子,这时候得分加一,当存在两个或更多的空堆时,游戏停止。我们需要计算游戏结束时我们最多可以得到多少分数。

我们可以分两种情况来讨论:

  • 首先我们假设 a <= b <= c

三个数的排序我们可以这样做:

[a,b,c] = [a,b,c].sort((a,b)=>a-b);
  • a + b <= c

这种情况下我们可以将ac中的石子全部取完,所以分数应该为a + b

  • a + b > c

这种情况下我们可以轮流从ab中取出石子和c中的石子配对,最终可以将c中的石子取完,且可以保证ab之间的石子数量之差小于等于1,所以这时的分数应该为c + Math.floor((a + b - c) / 2),化简后为Math.floor((a + b + c) / 2)

如果a + b <= c,那么Math.floor((a + b + c) / 2) >= a + b;如果a + b > c,那么Math.floor((a + b + c) / 2) < a + b 。所以我们只需要取Math.floor((a + b + c) / 2)a + b两者中的更小者即可,即:Math.min(Math.floor((a + b + c) / 2) , a + b)

AC代码

完整代码如下:

/**
 * @param {number} a
 * @param {number} b
 * @param {number} c
 * @return {number}
 */
var maximumScore = function(a, b, c) {
    [a,b,c] = [a,b,c].sort((a,b)=>a-b);
    return Math.min(Math.floor((a + b + c) / 2),a + b);
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。