题目描述
给定一个整数 total
,表示你拥有的总钱数。同时给你两个整数 cost1
和 cost2
,分别表示一支钢笔和一支铅笔的价格。你可以花费你部分或者全部的钱,去买任意数目的这两种笔。
请你返回购买钢笔和铅笔的不同方案数目。
示例
解题思路
这个问题可以通过暴力枚举的方式来解决。我们可以考虑购买不同数量的钢笔,然后计算剩余的金额购买铅笔的数量,最后统计所有可能的方案数。题目本身是通过枚举解决的,因此可以适当优化枚举降低复杂度。
具体的思路如下:
- 首先,如果两种笔的价格相同(
cost1 == cost2
),那么无论购买哪种笔,结果都是相同的。我们可以直接计算总共购买的数量,然后使用等差数列求和公式计算购买方案的数量。 - 如果
cost1
小于cost2
,我们可以通过递归的方式交换参数,并且利用递归中的计算结果。 - 对于一般情况,我们可以通过循环枚举购买钢笔的数量,然后计算剩余的金额购买铅笔的数量,最后累加所有可能的方案数。
代码实现
class Solution {
public:
long long waysToBuyPensPencils(int total, int cost1, int cost2) {
if (cost1 == cost2) {
return static_cast<long long>(total/cost1+2)*(total/cost1+1)/2;
}
if (cost1 < cost2) {
return waysToBuyPensPencils(total, cost2, cost1);
}
long long ans = 0;
for (int numPens = 0; numPens * cost1 <= total; numPens++) {
int remainingMoney = total - numPens * cost1;
ans += (remainingMoney / cost2) + 1;
}
return ans;
}
};
复杂度分析
对于给定的总金额 total
,我们需要分别考虑购买不同数量的钢笔和铅笔,然后统计购买方案数。因此,算法的时间复杂度主要由两部分组成:
- 首先,我们需要在购买钢笔的数量范围内进行循环,然后计算剩余金额购买铅笔的数量,最后统计购买方案数。购买钢笔的数量范围为
0
到total / cost1
,所以购买钢笔的循环次数为O(total / cost1)
。 - 在购买钢笔的循环中,我们需要计算剩余金额购买铅笔的数量,这个操作的时间复杂度为
O(1)
。
综上所述,算法的总时间复杂度为 O(total / cost1)
。
除了循环的时间复杂度外,空间复杂度主要取决于存储变量。算法使用了常数个变量因此空间复杂度为 O(1)
。
在特殊处理cost1和cost2后,击败了100%
的C++用户。