LeetCode 365:水壺問題(數學解)

LeetCode 365:水壺問題

有兩個容量分別爲 x升 和 y升 的水壺以及無限多的水。請判斷能否通過使用這兩個水壺,從而可以得到恰好 z升 的水?比如3升和 5升水壺,可以倒出 4 升水。

數學表達:mx + ny = z,求整數解

數學思路:根據貝祖公式,設c爲x和y的最大公約數,則一定存在等式c = mx+ny,m和n爲整數,並且mn < 0

因此,z只要是最大公約數的倍數即可。

最大公約數的求法

  1. 輾轉相除法:大數a/小數b,求餘數temp,若temp=0,則b爲最大公約數,否則,令a=b, b=temp;
  2. 更相減損法:a > b,它們的最大公約數等於a-b的差值c和較小數b的最大公約數。依次遞歸下去,直到兩個數相等。這相等兩個數的值就是所求最大公約數。
// 輾轉相除法
int gcd(int a, int b){
	int temp = a % b;
	while(temp!=0){
		a = b;
        b = temp;
        temp = a%b;  
    }  
    return b;                                                                         }
題解:
bool canMeasureWater(int x, int y, int z) {
    if(x+y<z) return false;
    if(x==0||y==0) return z==0|| x+y==z;
	int temp = x % y;
	while(temp!=0){
		x = y;
        y = temp;
        temp = x % y;  
    }  
    return z%y==0?true:false;
}
自己的思路(Fail)
bool canMeasureWater(int x, int y, int z) {
    // 假設桶id 0,1,分別對應大小x,y
    vector<int> bucket; bucket.push_back(x); bucket.push_back(y);
    // 假設飄動水量屬性water[餘量,桶id],初始情況有二
    // 設置數組,記錄能否獲得相應水量,初始化大小爲[x+y+1],並設置真值
    vector<bool> res(x + y + 1, false); res[0] = true;
    // 設置終止條件,當水的餘量和桶id已經有記錄,就退出。
    map<int, int> endjudge;
    for (int i = 0; i < 2; i++) {
        pair<int, int> water(bucket[i], i);
        while (endjudge.find(water.first) == endjudge.end() || (*endjudge.find(water.first)).second != water.second) {
            int otherbucid = (water.second + 1) % 2;
            res[water.first] = true; res[water.first + bucket[otherbucid]] = true;
            if (water.first > bucket[otherbucid]) {
                water.first -= bucket[otherbucid]; // 倒給另一個桶,還有剩餘
                endjudge.insert(water);
                break;
            }
            else {
                water.first = bucket[water.second]-(bucket[otherbucid]-water.first);
                water.second = otherbucid; // 全倒給另一個桶,或者不到出,這個判斷就傻了。
            }
        }
    }
    return res[z];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章