Leetcode - 365. 水壶问题 / 倒水问题 / 栈模拟递归 / gcd
思路:
- 第一想法肯定是用DFS模拟倒水操作,因为每个杯子最多就三次操作,然后记录一下每次的状态,但是会超过循环的次数,所以改用栈来模拟循环。
- 官方题解的数学方法,即如果z是x和y公约数的倍数那么本次操作一定能完成(官方在题解里面推导了,原理没看懂,数学蒟蒻,先记下来好了)
"""
栈模拟递归
"""
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
if x == z or y == z or x + y == z:
return True
if x + y < z:
return False
vis = set()
stack = [(x, y)]
while stack:
tx, ty = stack.pop()
if (tx, ty) in vis:
continue
# 记录搜索过的状态
vis.add((tx, ty))
if tx == z or ty == z or tx + ty == z:
return True
# x清空,x倒满,x给y倒水
stack.append((0, ty))
stack.append((x, ty))
stack.append((max(0, tx - ty), min(y, ty + tx)))
# y清空,y倒满,y给x倒水
stack.append((tx, 0))
stack.append((tx, y))
stack.append((min(x, ty + tx), max(0, ty-tx)))
return False
"""
对于数学方法而言,题目已经转换为了求最大公约数了。
"""
class Solution:
def canMeasureWater(self, x: int, y: int, z: int) -> bool:
if x == z or y == z or x + y == z:
return True
if x + y < z:
return False
def gcd(x, y):
if x % y == 0:
return y
return gcd(y, x % y)
return True if not z % gcd(x, y) else False