365. 水壶问题
有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?
如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
你允许:
装满任意一个水壶
清空任意一个水壶
从一个水壶向另外一个水壶倒水,直到装满或者倒空
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/water-and-jug-problem
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
搜索
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;
class Solution {
private String getKey(int x, int y) {
return x + "_" + y;
}
private void add(LinkedList<State> queue, Set<String> stateSet, int x, int y) {
String key = getKey(x, y);
if (!stateSet.contains(key)) {
queue.offer(new State(x, y));
stateSet.add(key);
}
}
public boolean canMeasureWater(int x, int y, int z) {
LinkedList<State> queue = new LinkedList<>();
Set<String> stateSet = new HashSet<>();
add(queue, stateSet, 0, 0);
while (!queue.isEmpty()) {
State state = queue.poll();
if (state.x == z || state.y == z || state.x + state.y == z) {
return true;
}
add(queue, stateSet, 0, state.y);
add(queue, stateSet, state.x, 0);
add(queue, stateSet, x, state.y);
add(queue, stateSet, state.x, y);
add(queue, stateSet, state.x + Math.min(state.y, x - state.x), state.y - Math.min(state.y, x - state.x));
add(queue, stateSet, state.x - Math.min(state.x, y - state.y), state.y + Math.min(state.x, y - state.y));
}
return false;
}
}
class State {
int x;
int y;
public State(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
State state = (State) o;
return x == state.x &&
y == state.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
贝祖定理
class Solution {
private int gcd(int x, int y) {
while (y != 0) {
int remainder = x % y;
x = y;
y = remainder;
}
return x;
}
public boolean canMeasureWater(int x, int y, int z) {
if (x + y < z) {
return false;
}
if (x == z || y == z || x + y == z) {
return true;
}
return z % gcd(x, y) == 0;
}
}
心之所向,素履以往 生如逆旅,一苇以航