【LeetCode】365.水壶问题
题目描述
解题思路
思路一:裴蜀定理-数学法
- 由题意,每次操作只会让桶里的水总量增加x或y,或者减少x或y,即会给水的总量带来x或y的变化量,转为数字描述即为:找到一对整数a,b使得下式成立:
ax+by=z
- 分析知,要完成操作,需要满足:
z<=x+y(a,b存在)
- 由裴蜀定理:
z是x,y的最大公约数的倍数=>ax+by=z有解
// C++
class Solution {
public:
bool canMeasureWater(int x, int y, int z) {
if(x + y < z)
return false;
if(x == 0 || y == 0)
return (z == 0 || x + y == z);
return (z % gcd(x, y) == 0);
}
};
// T(n) = O(log(min(x,y)),即计算最大公约数所使用的辗转相除法
// S(n) = O(1)
思路二:DFS
- 对题目进行建模,分析可知,在任意一个时刻,问题的状态有两个数字决定:X壶中的水量,以及Y壶中的水量;
- 可以采取以下操作:
- 把X壶的水灌进Y壶,直至灌满或者倒空;
- 把Y壶的水灌进Y壶,直至灌满或者倒空;
- 把X壶灌满;
- 把Y壶灌满;
- 把X壶倒空;
- 把Y壶倒空;
- 搜索中的每一步以 remain_x, remain_y 作为状态,即表示 X 壶和 Y 壶中的水量。在每一步搜索时,我们会依次尝试所有的操作,递归地搜索下去。但要保证每个状态至多只被搜索一次。
# Python
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
stack = [(0, 0)]
self.seen = set()
while stack:
remain_x, remain_y = stack.pop()
if remain_x == z or remain_y == z or remain_x + remain_y == z:
return True
if (remain_x, remain_y) in self.seen:
continue
self.seen.add((remain_x, remain_y))
# 把 X 壶灌满。
stack.append((x, remain_y))
# 把 Y 壶灌满。
stack.append((remain_x, y))
# 把 X 壶倒空。
stack.append((0, remain_y))
# 把 Y 壶倒空。
stack.append((remain_x, 0))
# 把 X 壶的水灌进 Y 壶,直至灌满或倒空。
stack.append((remain_x - min(remain_x, y - remain_y), remain_y + min(remain_x, y - remain_y)))
# 把 Y 壶的水灌进 X 壶,直至灌满或倒空。
stack.append((remain_x + min(remain_y, x - remain_x), remain_y - min(remain_y, x - remain_x)))
return False
# T(n) = O(xy),状态数最多有(x+1)(y+1)种,每一种状态进行DFS为O(1)
# S(n) = O(xy),set存入状态数
总结
- DSA相关:相关数据结构为栈,哈希表,相关的算法为数学。
- 语言相关:由于深度优先搜索导致的递归远远超过了 Python 的默认递归层数,使用栈来模拟递归,避免了真正使用递归而导致的问题。
- 其他:数学结论也很重要啊!
【LeetCode】365.水壶问题的更多相关文章
- Java实现 LeetCode 365 水壶问题
365. 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水. ...
- Leetcode 365.水壶问题
水壶问题 有两个容量分别为 x升和 y升的水壶以及无限多的水.请判断能否通过使用这两个水壶,从而可以得到恰好 z升的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水. 你允许: 装满 ...
- Leetcode 365. Water and Jug Problem
可以想象有一个无限大的水罐,如果我们有两个杯子x和y,那么原来的问题等价于是否可以通过往里面注入或倒出水从而剩下z. z =? m*x + n*y 如果等式成立,那么z%gcd(x,y) == 0. ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- C#LeetCode刷题-数学
数学篇 # 题名 刷题 通过率 难度 2 两数相加 29.0% 中等 7 反转整数 C#LeetCode刷题之#7-反转整数(Reverse Integer) 28.6% 简单 8 字符串转整数 ...
- LeetCode刷题总结-数学篇
本文总结LeetCode上有数学类的算法题,推荐刷题总数为40道.具体考点分析如下图: 1.基本运算问题 题号:29. 两数相除,难度中等 题号:166. 分数到小数,难度中等 题号:372. 超级次 ...
- 【LeetCode】2020-03 每日一题
121. 买卖股票的最佳时机(简单) [分类]:模拟.思维 [题解]:可以用O(n)的复杂度完成,只需要在遍历的时候记录到当前位置为止买入股票的最小价格minn,再维护一个当前卖出股票价(a-minn ...
- leedcode算法解题思路
1.两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个 ...
- LeetCode 461 汉明距离/LintCode 365 统计二进制中1的个数
LeetCode 461. 汉明距离 or LintCode 365. 二进制中有多少个1 题目一:LeetCode 461. 汉明距离 LeetCode 461.明距离(Hamming Distan ...
随机推荐
- CSP-S 2020 游记
2020.10.11 初赛了,没怎么做题,之前在网上两次初赛模拟赛 95pts / 94pts,还白嫖了一本书,感觉挺好. 去考场,中途不舒服去了厕所,回来发现有点来不及,阅读程序最后两题不会瞎蒙. ...
- 题解-CF1282E The Cake Is a Lie
题面 CF1282E The Cake Is a Lie \(T\) 组测试数据.每次给一个 \(n\) 边形的三角剖分,求节点顺序和剖分顺序. 数据范围:\(3\le n\le 10^5\),\(\ ...
- React Native学习记录
1.端口问题 在调试的时候,监听的是8081端口.如果被占用,会报错,并且在reload的时候导致app直接崩掉. 2.插件网站收集 https://nativebase.io/ https://js ...
- PhotoSwipe用法
1.自动识别data-size问题,添加以下代码 gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options) ...
- Django使用channels实现Websocket连接
简述: 需求:消息实时推送消息以及通知功能,采用django-channels来实现websocket进行实时通讯.并使用docker.daphne启动通道,保持websocket后台运行 介绍Dja ...
- 实验4 汇编应用编程和c语言程序反汇编分析
1. 实验任务1 教材「实验9 根据材料编程」(P187-189)编程:在屏幕中间分别显示绿色.绿底红色.白底蓝色的字符串'welcome to masm!'. 解题思路:根据学习的知识,我知道该页在 ...
- Numpy的学习3-索引
import numpy as np A = np.arange(3, 15) # array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]) print(A[3 ...
- vscode php转到定义
点击再settings.json 中编辑 添加这一行,内容为php的安装路径
- webform中ajax.ajaxMethod使用方法
前言 dll文件 如果还没有ajax.dll文件,就先下载一个来 引用 将ajax.dll添加到项目引用中:在VS的解决方案资源管理器中右键点击项目名称--"添加项目引用"--浏览 ...
- CentOS8更换国内YUM源
rm -rf /etc/yum.repos.d/* wget -O /etc/yum.repos.d/CentOS-cnnic.repo https://feieryun.oss-cn-zhangji ...