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];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章