LeetCode破解之令牌放置

296 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

题目说明

你的初始 能量 为 P,初始 分数 为 0,只有一包令牌 tokens 。其中 tokens[i] 是第 i 个令牌的值(下标从 0 开始)。

令牌可能的两种使用方法如下:

如果你至少有 token[i] 点 能量 ,可以将令牌 i 置为正面朝上,失去 token[i] 点 能量 ,并得到 1 分 。 如果我们至少有 1 分 ,可以将令牌 i 置为反面朝上,获得 token[i] 点 能量 ,并失去 1 分 。 每个令牌 最多 只能使用一次,使用 顺序不限 ,不需 使用所有令牌。

在使用任意数量的令牌后,返回我们可以得到的最大 分数 。

示例 1:

输入:tokens = [100], P = 50 输出:0 解释:无法使用唯一的令牌,因为能量和分数都太少了。

思路分析

看完题目,能想到的思路很简单,我们只有两种操作,正翻最小牌并反翻最大牌,获取分数并继续翻牌,或结束游戏,用手中所有分数尽可能多地正翻牌以获取分数。先把小牌尽量换成分数,换不了如果还有>1张牌再把最大的数换成能量,重复这个过程

贪心算法

思路:

我们先对令牌从小到大进行排序,并计算令牌的总和total;
左指针l代表当前情况下的最小令牌(初始为0),右指针r代表当前的最大令牌(初始为len-1),这样设计的原因是我们每次在兑换的时候希望用最小的令牌换取最大的令牌;
对于某一情况的能量p,存在几种情形:

- 先从小到大排序
- 对排序后的结果,先从左开始遍历
  - 如果当前token的值小于power,则积分加1,同时从power中扣除对应的能量值(当前toekn值),左指针右移。
  - 否则,如果积分大于0,扣除一个积分,然后把最大令牌反转,把最大令牌的值加到power里面,右指针左移。
class Solution {
    public int bagOfTokensScore(int[] tokens, int power) {
        int max_grade = 0,grade = 0;
        Boolean get_new = true;
        Arrays.sort(tokens);
        int left = 0, right = tokens.length - 1;
        do{
            get_new = false;
            while(left <= right && tokens[left] <= power){
                grade++;
                power -= tokens[left];
                left ++;
                max_grade = Math.max(max_grade, grade);
                get_new = true;
            }
            if(grade > 0){
                power += tokens[right];
                grade--;
                right--;
                get_new = true;
            }
        }
        while(left <right && get_new);
        return max_grade;
    }
}

注意

入手最便宜的分,将分换最贵的能量,来得到更大的能量潜力 能买就买,不能买,去用分兑换更大的,再来买。刚开始我还是低估了这个题 主要思路就是,两个牌一个牌分高一个牌分低,我一正一反就多了能量,所以只要加上能量能有新的分可以加,就不亏。