思路:

题目的主要信息:

  • 1红球+1黄球+1蓝球=1彩票
  • 1红球=2黄球+1蓝球
  • 1黄球=2蓝球+1红球
  • 1蓝球=2红球+1黄球

球的相互兑换是循环的,要求最多可兑换的彩票数

方法一:过程模拟+贪心
具体做法:
采用贪心思想,因为球换球不划算,所以先把能兑换彩票的球换完,再考虑球换球。
在abc不为0的情况下,每个参数减1,彩票数加1。一旦有一个数(假设是a)为0,用另外两个数来换球,这种时候需要3个b球+2个c球才能换一张彩票,最后换到只剩一种颜色的球为止。。因为是一个循环,所以不管是哪个球先被耗尽,另外两个球都能表示。
图片说明

class Solution {
public:
    int two_color_ball(int x, int y){ //用两种球换另一种球,并加上两种球本身换彩排
        int count = 0;
        while(x > 0 && y > 0){
            x -= 3;
            y -= 2;
            if(x >= 0 && y >= 0)
                count++;
        }
        return count;
    }
    int solve(int a, int b, int c) {
        int res = 0;
        while(a > 0 && b > 0 && c > 0){ //优先换完
            a--;
            b--;
            c--;
            res++;
        }
        if(a == 0){ //红球没有换红球
            res += two_color_ball(b, c);
        }else if(b == 0){//黄球没有换黄球
            res += two_color_ball(c, a);
        }else {//蓝球没有换蓝球
            res += two_color_ball(a, b);
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,最多不超过这个复杂度,精确复杂度不可求
  • 空间复杂度:,无额外空间

方法二:数学+贪心
具体做法:
上述模拟过程可以直接用数学来表现:第一个循环,可以直接找到abc三者最小值,可以直接都减去这个最小值,取到最小的那个为0.
再来看谁是0,另外两种球,一种是除以3,一种是除以2,找最小次数。

class Solution {
public:
    int solve(int a, int b, int c) {
        int res = min(a, min(b, c)); //取三者最小
        a -= res;
        b -= res;
        c -= res;
        if(a == 0)  //一种为0,用另外两种来换
            return res + min(b / 3, c / 2);
        else if(b == 0)
            return res + min(c / 3, a / 2);
        else if(c == 0)
            return res + min(a / 3, b / 2);
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,无循环,常数时间
  • 空间复杂度:,常数空间