Leetcode365 水壶问题

leetcode 水壶问题

水壶问题

在这里插入图片描述每日一题,有点偏数学,但是可以用图论的BFD 和DFS 求解。
关于二叉树的BFS和DFS已经进行过介绍,本文主要是图论的BFS和DFS。
首先对题目进行建模。观察题目可知,在任意一个时刻,此问题的状态可以由两个数字决定:X 壶中的水量,以及 Y 壶中的水量。

在任意一个时刻,我们可以且仅可以采取以下几种操作或者是只存在如下的状态转移可能:

把 X 壶的水灌进 Y 壶,直至灌满或倒空;
把 Y 壶的水灌进 X 壶,直至灌满或倒空;
把 X 壶灌满;
把 Y 壶灌满;
把 X 壶倒空;
把 Y 壶倒空。

因此可以用搜索的方法解决问题。

首先是广度优先

class Solution(object):
    def canMeasureWater(self, x, y, z):
        """
        :type x: int
        :type y: int
        :type z: int
        :rtype: bool
        """
        # bfs
        from collections import deque
        queue = deque([[0, 0]]) # 双向队列
        visited = set([(0, 0)]) # 标记哪些状态已经处理过了
		# 开始递推状态
        while queue:
            cur_x, cur_y = queue.pop()  # 广度优先 
            # 结束循环的条件
            if z in [cur_x, cur_y, cur_x + cur_y]:
                return True 
            # 可能转移到下列可能的状态
            for item in [
                # 加满水
                (x, cur_y), (cur_x, y),
                # 清空水
                (0, cur_y), (cur_x, 0),
                # x -> y
                (cur_x + cur_y - y, y) if cur_x + cur_y >= y else (0, cur_x + cur_y),
                # y -> x
                (x, cur_x + cur_y - x) if cur_x + cur_y >= x else (cur_x + cur_y, 0)]:
                # 为防止成环,对邻居进行标记
                if item not in visited:
                    queue.appendleft(item)
                    visited.add(item)
        return False

这种方法的在得到结果的时候就会结束,不用遍历整个图,相对复杂度比较低。

深度优先

class Solution:
    def canMeasureWater(self, x: int, y: int, z: int) -> bool:  
        visited = set()

        def helper(cur_x, cur_y):
            # print(cur_x, cur_y)
            if z in [cur_x, cur_y, cur_x + cur_y]:
                return True
            for item in [
                # 加满水
                (x, cur_y), (cur_x, y),
                # 清空水
                (0, cur_y), (cur_x, 0),
                # x -> y
                (cur_x + cur_y - y, y) if cur_x + cur_y >= y else (0, cur_x + cur_y),
                # y -> x
                (x, cur_x + cur_y - x) if cur_x + cur_y >= x else (cur_x + cur_y, 0)]:
                if item not in visited:
                    visited.add(item)
                    if helper(*item): return True
                    visited.remove(item)

            return False

        return helper(x, y)

数学方法

裴蜀定理

若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立

class Solution:
    def canMeasureWater(self, x: int, y: int, z: int) -> bool:  
        import math
        if x + y < z: return False
        if x == z or y == z or x + y == z: return True
        return z % math.gcd(x, y) == 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值