LeetCode第365题_水壶问题
LeetCode 第365题:水壶问题
📖 文章摘要
本文详细解析LeetCode第365题"水壶问题",这是一道数学和广度优先搜索问题。文章提供了基于数学和BFS的两种解法,包含C#、Python、C++三种语言实现,配有详细的算法分析和性能对比。适合想要提升数学思维和搜索算法的读者。
核心知识点: 数学、广度优先搜索、最大公约数、状态搜索
难度等级: 中等
推荐人群: 具有基础算法知识,想要提升数学思维的程序员
题目描述
有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?
如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
你允许:
- 装满任意一个水壶
- 清空任意一个水壶
- 从一个水壶向另外一个水壶倒水,直到装满或者倒空
示例
示例 1:
输入:x = 3, y = 5, z = 4
输出:True
解释:我们可以先装满5升的水壶,然后倒3升到3升的水壶中,此时5升水壶中剩余2升水。然后倒空3升水壶,将5升水壶中的2升水倒入3升水壶中。最后装满5升水壶,此时5升水壶中有5升水,3升水壶中有2升水,总共7升水。然后从5升水壶中倒出1升水到3升水壶中,此时5升水壶中有4升水,3升水壶中有3升水,总共7升水。所以我们可以得到4升水。
示例 2:
输入:x = 2, y = 6, z = 5
输出:False
解释:我们无法得到5升水。
提示
0 <= x <= 10^6
0 <= y <= 10^6
0 <= z <= 10^6
解题思路
本题可以使用数学或BFS解决:
-
数学解法:
- 使用贝祖定理
- 判断z是否能被x和y的最大公约数整除
-
BFS解法:
- 使用队列进行状态搜索
- 记录已访问的状态
- 枚举所有可能的操作
时间复杂度:
- 数学解法:O(log(min(x,y)))
- BFS解法:O(xy)
空间复杂度:
- 数学解法:O(1)
- BFS解法:O(xy)
🎯 算法流程演示
图解思路
数学解法
步骤 | 操作 | 说明 |
---|---|---|
1 | 计算gcd(x,y) | 使用辗转相除法 |
2 | 判断z%gcd==0 | 判断是否有解 |
3 | 判断z<=x+y | 判断是否可行 |
BFS状态转移
状态 | 操作 | 新状态 |
---|---|---|
(a,b) | 装满x | (x,b) |
(a,b) | 装满y | (a,y) |
(a,b) | 倒空x | (0,b) |
(a,b) | 倒空y | (a,0) |
(a,b) | x倒入y | (max(0,a+b-y),min(y,a+b)) |
(a,b) | y倒入x | (min(x,a+b),max(0,a+b-x)) |
代码实现
C# 实现
public class Solution {public bool CanMeasureWater(int x, int y, int z) {if (z == 0) return true;if (x + y < z) return false;return z % GCD(x, y) == 0;}private int GCD(int a, int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;}
}
Python 实现
class Solution:def canMeasureWater(self, x: int, y: int, z: int) -> bool:if z == 0:return Trueif x + y < z:return Falsedef gcd(a, b):while b:a, b = b, a % breturn areturn z % gcd(x, y) == 0
C++ 实现
class Solution {
public:bool canMeasureWater(int x, int y, int z) {if (z == 0) return true;if (x + y < z) return false;return z % gcd(x, y) == 0;}private:int gcd(int a, int b) {while (b) {int temp = b;b = a % b;a = temp;}return a;}
};
执行结果
C# 实现
- 执行用时:36 ms
- 内存消耗:14.8 MB
Python 实现
- 执行用时:28 ms
- 内存消耗:13.2 MB
C++ 实现
- 执行用时:0 ms
- 内存消耗:5.9 MB
性能对比
语言 | 执行用时 | 内存消耗 | 特点 |
---|---|---|---|
C++ | 0 ms | 5.9 MB | 执行效率最高,内存占用最小 |
Python | 28 ms | 13.2 MB | 代码简洁,内存占用适中 |
C# | 36 ms | 14.8 MB | 类型安全,内存占用较大 |
代码亮点
- 🎯 使用数学方法优雅解决
- 💡 处理边界情况和特殊情况
- 🔍 使用辗转相除法计算最大公约数
- 🎨 代码结构清晰,易于维护
常见错误分析
- 🚫 未处理z=0的情况
- 🚫 未处理x+y<z的情况
- 🚫 最大公约数计算错误
- 🚫 整数溢出
解法对比
解法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
---|---|---|---|---|
数学解法 | O(log(min(x,y))) | O(1) | 高效,实现简单 | 需要数学知识 |
BFS解法 | O(xy) | O(xy) | 直观,易于理解 | 效率较低 |
相关题目
- LeetCode 365. 水壶问题 - 中等
- LeetCode 279. 完全平方数 - 中等
- LeetCode 322. 零钱兑换 - 中等
📖 系列导航
🔥 算法专题合集 - 查看完整合集
📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新第365题。
💬 互动交流
感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。
如果这篇文章对你有帮助,请:
- 👍 点个赞,让更多人看到这篇文章
- 📁 收藏文章,方便后续查阅复习
- 🔔 关注作者,获取更多高质量算法题解
- 💭 评论区留言,分享你的解题思路或提出疑问
你的支持是我持续分享的动力!
💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!
💬 互动交流
感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。
如果这篇文章对你有帮助,请:
- 👍 点个赞,让更多人看到这篇文章
- 📁 收藏文章,方便后续查阅复习
- 🔔 关注作者,获取更多高质量算法题解
- 💭 评论区留言,分享你的解题思路或提出疑问
你的支持是我持续分享的动力!
💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!