水壺問題詳解

想了解更多數據結構以及算法題,可以關注微信公衆號“數據結構和算法”,每天一題爲你精彩解答。也可以掃描下面的二維碼關注
在這裏插入圖片描述
有兩個容量分別爲 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肯定是一個爲正數一個爲負數,也就是一個總共裝了幾桶水,一個總共倒了幾桶水。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章