LeetCode 题解工作台

水壶问题

有两个水壶,容量分别为 x 和 y 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 target 升。 你可以: 装满任意一个水壶 清空任意一个水壶 将水从一个水壶倒入另一个水壶,直到接水壶已满,或倒水壶已空。 示例 1: 输入: x = 3,y = 5,target = 4 输出: tr…

category

3

题型

code_blocks

4

代码语言

hub

3

相关题

当前训练重点

中等 · 图·搜索

bolt

答案摘要

我们不妨记 为 , 为 , 为 。 接下来,我们设计一个函数 $dfs(i, j)$,表示当前 中有 升水, 中有 升水,是否可以得到 升水。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 图·搜索 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

有两个水壶,容量分别为 x 和 y 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 target 升。

你可以:

  • 装满任意一个水壶
  • 清空任意一个水壶
  • 将水从一个水壶倒入另一个水壶,直到接水壶已满,或倒水壶已空。

 

示例 1: 

输入: x = 3,y = 5,target = 4
输出: true
解释:
按照以下步骤操作,以达到总共 4 升水:
1. 装满 5 升的水壶(0, 5)。
2. 把 5 升的水壶倒进 3 升的水壶,留下 2 升(3, 2)。
3. 倒空 3 升的水壶(0, 2)。
4. 把 2 升水从 5 升的水壶转移到 3 升的水壶(2, 0)。
5. 再次加满 5 升的水壶(2, 5)。
6. 从 5 升的水壶向 3 升的水壶倒水直到 3 升的水壶倒满。5 升的水壶里留下了 4 升水(3, 4)。
7. 倒空 3 升的水壶。现在,5 升的水壶里正好有 4 升水(0, 4)。
参考:来自著名的 "Die Hard"

示例 2:

输入: x = 2, y = 6, target = 5
输出: false

示例 3:

输入: x = 1, y = 2, target = 3
输出: true
解释:同时倒满两个水壶。现在两个水壶中水的总量等于 3。

 

提示:

  • 1 <= x, y, target <= 103
lightbulb

解题思路

方法一:DFS

我们不妨记 jug1Capacity\textit{jug1Capacity}xx, jug2Capacity\textit{jug2Capacity}yy, targetCapacity\textit{targetCapacity}zz

接下来,我们设计一个函数 dfs(i,j)dfs(i, j),表示当前 jug1jug1 中有 ii 升水,jug2jug2 中有 jj 升水,是否可以得到 zz 升水。

函数 dfs(i,j)dfs(i, j) 的执行过程如下:

  • 如果 (i,j)(i, j) 已经被访问过,返回 falsefalse
  • 如果 i=zi = z 或者 j=zj = z 或者 i+j=zi + j = z,返回 truetrue
  • 如果我们给 jug1jug1 倒满水,或者给 jug2jug2 倒满水,或者将 jug1jug1 清空,或者将 jug2jug2 清空,可以得到 zz 升水,返回 truetrue
  • 如果我们将 jug1jug1 中的水倒入 jug2jug2,或者将 jug2jug2 中的水倒入 jug1jug1,可以得到 zz 升水,返回 truetrue

答案即为 dfs(0,0)dfs(0, 0)

时间复杂度 O(x+y)O(x + y),空间复杂度 O(x+y)O(x + y)。其中 xxyy 分别为 jug1Capacity\textit{jug1Capacity}jug2Capacity\textit{jug2Capacity}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
    def canMeasureWater(self, x: int, y: int, z: int) -> bool:
        def dfs(i: int, j: int) -> bool:
            if (i, j) in vis:
                return False
            vis.add((i, j))
            if i == z or j == z or i + j == z:
                return True
            if dfs(x, j) or dfs(i, y) or dfs(0, j) or dfs(i, 0):
                return True
            a = min(i, y - j)
            b = min(j, x - i)
            return dfs(i - a, j + a) or dfs(i + b, j - b)

        vis = set()
        return dfs(0, 0)
speed

复杂度分析

指标
时间and space complexity depend on the approach: the DFS/BFS can explore up to O(x*y) unique jug states, while the GCD method runs in constant time O(log(min(x,y))). Using state pruning reduces unnecessary recursion and queue expansions.
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    They may hint at mathematical properties like GCD to optimize the solution.

  • question_mark

    Expect questions on avoiding infinite loops when simulating jug operations.

  • question_mark

    They often check understanding of BFS vs DFS trade-offs in state exploration.

warning

常见陷阱

外企场景
  • error

    Failing to check the GCD condition and running full DFS unnecessarily.

  • error

    Not marking visited states, causing infinite recursion or repeated computations.

  • error

    Assuming the target must be in a single jug instead of the total combined water.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Compute the minimum number of steps to reach the target liters using BFS.

  • arrow_right_alt

    Allow fractional jug capacities and target values to test floating-point handling.

  • arrow_right_alt

    Generalize to three or more jugs with arbitrary capacities and target liters.

help

常见问题

外企场景

水壶问题题解:图·搜索 | LeetCode #365 中等