想了解更多數據結構以及算法題,可以關注微信公衆號“數據結構和算法”,每天一題爲你精彩解答。也可以掃描下面的二維碼關注
有兩個容量分別爲 x升 和 y升 的水壺以及無限多的水。請判斷能否通過使用這兩個水壺,從而可以得到恰好 z升 的水?
如果可以,最後請用以上水壺中的一或兩個來盛放取得的 z升 水。
你允許:
- 裝滿任意一個水壺
- 清空任意一個水壺
- 從一個水壺向另外一個水壺倒水,直到裝滿或者倒空
示例 1:
輸入: x = 3, y = 5, z = 4
輸出: True
示例 2:
輸入: x = 2, y = 6, z = 5
輸出: False
答案:
public boolean canMeasureWater1(int x, int y, int z) {
return z == 0 || (long) x + y >= z && z % gcd(x, y) == 0;
}
public int gcd(int x, int y) {//求x,y的最大公約數
return y == 0 ? x : gcd(y, x % y);
}
解析:
這題估計大家都遇到過好多次了,即使沒在面試中遇到過,但至少在書上也看到過。這題如果單從代碼上來看基本上沒什麼難度,難的是對這題的理解,其實這裏面涉及到一個定理叫裴蜀定理。需要理解他,這題才能看明白。下面再來看一種解法,
public boolean canMeasureWater(int x, int y, int z) {
if (z < 0 || z > x + y) {
return false;
}
Set<Integer> set = new HashSet<>();
Queue<Integer> q = new LinkedList<>();
q.offer(0);
while (!q.isEmpty()) {
int n = q.poll();
int top = n - y;
if (top >= 0 && set.add(top)) {
q.offer(top);
}
int down = n + y;
if (down <= x + y && set.add(down)) {
q.offer(down);
}
int left = n - x;
if (left >= 0 && set.add(left)) {
q.offer(left);
}
int right = n + x;
if (right <= x + y && set.add(right)) {
q.offer(right);
}
if (set.contains(z)) {
return true;
}
}
return false;
}
以原點0爲中心,向他的上下左右4個方向發散,所以最終會滿足一個方程ax+by=z,並且a,b都是整數,如果x,y,z都不爲0的情況下,當且僅當x+y=z的時候,a=b=1,否則如果滿足條件,a和b肯定是一個爲正數一個爲負數,也就是一個總共裝了幾桶水,一個總共倒了幾桶水。