leetcode 力扣 365 水壶问题题解 算法题.docx
《leetcode 力扣 365 水壶问题题解 算法题.docx》由会员分享,可在线阅读,更多相关《leetcode 力扣 365 水壶问题题解 算法题.docx(15页珍藏版)》请在冰豆网上搜索。
![leetcode 力扣 365 水壶问题题解 算法题.docx](https://file1.bdocx.com/fileroot1/2022-11/27/29f3cb6b-c780-4671-b83a-3d85e69081ca/29f3cb6b-c780-4671-b83a-3d85e69081ca1.gif)
leetcode力扣365水壶问题题解算法题
题目:
水壶问题
有两个容量分别为 x升和y升的水壶以及无限多的水。
请判断能否通过使用这两个水壶,从而可以得到恰好 z升的水?
如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
你允许:
•装满任意一个水壶
•清空任意一个水壶
•从一个水壶向另外一个水壶倒水,直到装满或者倒空
示例1:
(Fromthefamous"DieHard"example)
输入:
x=3,y=5,z=4
输出:
True
示例2:
输入:
x=2,y=6,z=5
输出:
False
语言:
Python
classSolution:
defcanMeasureWater(self,x:
int,y:
int,z:
int)->bool:
stack=[(0,0)]
self.seen=set()
whilestack:
remain_x,remain_y=stack.pop()
ifremain_x==zorremain_y==zorremain_x+remain_y==z:
returnTrue
if(remain_x,remain_y)inself.seen:
continue
self.seen.add((remain_x,remain_y))
#把X壶灌满。
stack.append((x,remain_y))
#把Y壶灌满。
stack.append((remain_x,y))
#把X壶倒空。
stack.append((0,remain_y))
#把Y壶倒空。
stack.append((remain_x,0))
#把X壶的水灌进Y壶,直至灌满或倒空。
stack.append((remain_x-min(remain_x,y-remain_y),remain_y+min(remain_x,y-remain_y)))
#把Y壶的水灌进X壶,直至灌满或倒空。
stack.append((remain_x+min(remain_y,x-remain_x),remain_y-min(remain_y,x-remain_x)))
returnFalse
语言:
Python
classSolution:
defcanMeasureWater(self,x:
int,y:
int,z:
int)->bool:
ifx+yreturnFalse
ifx==0ory==0:
returnz==0orx+y==z
returnz%math.gcd(x,y)==0
语言:
C++
usingPII=pair;
classSolution{
public:
boolcanMeasureWater(intx,inty,intz){
stackstk;
stk.emplace(0,0);
autohash_function=[](constPII&o){returnhash()(o.first)^hash()(o.second);};
unordered_setseen(0,hash_function);
while(!
stk.empty()){
if(seen.count(stk.top())){
stk.pop();
continue;
}
seen.emplace(stk.top());
auto[remain_x,remain_y]=stk.top();
stk.pop();
if(remain_x==z||remain_y==z||remain_x+remain_y==z){
returntrue;
}
//把X壶灌满。
stk.emplace(x,remain_y);
//把Y壶灌满。
stk.emplace(remain_x,y);
//把X壶倒空。
stk.emplace(0,remain_y);
//把Y壶倒空。
stk.emplace(remain_x,0);
//把X壶的水灌进Y壶,直至灌满或倒空。
stk.emplace(remain_x-min(remain_x,y-remain_y),remain_y+min(remain_x,y-remain_y));
//把Y壶的水灌进X壶,直至灌满或倒空。
stk.emplace(remain_x+min(remain_y,x-remain_x),remain_y-min(remain_y,x-remain_x));
}
returnfalse;
}
};
语言:
C++
classSolution{
public:
boolcanMeasureWater(intx,inty,intz){
if(x+yreturnfalse;
}
if(x==0||y==0){
returnz==0||x+y==z;
}
returnz%gcd(x,y)==0;
}
};
语言:
C++
classSolution{
inlinepairop(inttype,constpair&state,intx,inty){
switch(type){
case0:
returnmake_pair(x,state.second);
case1:
returnmake_pair(state.first,y);
case2:
returnmake_pair(0,state.second);
case3:
returnmake_pair(state.first,0);
case4:
{
intmove=min(state.first,y-state.second);
returnmake_pair(state.first-move,state.second+move);
}
case5:
{
intmove=min(x-state.first,state.second);
returnmake_pair(state.first+move,state.second-move);
}
}
returnmake_pair(0,0);
}
structHashPair{
size_toperator()(constpair&key)constnoexcept
{
return(size_t(key.first)<<31)|size_t(key.second);
}
};
inlineint64_tHash(intx,inty){
returnint64_t(x)<<32|y;
}
public:
boolcanMeasureWater(intx,inty,intz){
if(x+yreturnfalse;
}
unordered_setmark;//pair换成int64_t,但是意义不大。
queue>q;
q.push(make_pair(0,0));
while(q.empty()==false){
autof=q.front();
q.pop();
if(f.first+f.second==z){
returntrue;
}
for(inti=0;i<6;i++){
autonext=op(i,f,x,y);
int64_th=Hash(next.first,next.second);
if(mark.find(h)!
=mark.end()){
continue;
}
mark.insert(h);
q.push(next);
}
}
returnfalse;
}
};
语言:
Java
classSolution{
publicbooleancanMeasureWater(intx,inty,intz){
Dequestack=newLinkedList();
stack.push(newint[]{0,0});
Setseen=newHashSet();
while(!
stack.isEmpty()){
if(seen.contains(hash(stack.peek()))){
stack.pop();
continue;
}
seen.add(hash(stack.peek()));
int[]state=stack.pop();
intremain_x=state[0],remain_y=state[1];
if(remain_x==z||remain_y==z||remain_x+remain_y==z){
returntrue;
}
//把X壶灌满。
stack.push(newint[]{x,remain_y});
//把Y壶灌满。
stack.push(newint[]{remain_x,y});
//把X壶倒空。
stack.push(newint[]{0,remain_y});
//把Y壶倒空。
stack.push(newint[]{remain_x,0});
//把X壶的水灌进Y壶,直至灌满或倒空。
stack.push(newint[]{remain_x-Math.min(remain_x,y-remain_y),remain_y+Math.min(remain_x,y-remain_y)});
//把Y壶的水灌进X壶,直至灌满或倒空。
stack.push(newint[]{remain_x+Math.min(remain_y,x-remain_x),remain_y-Math.min(remain_y,x-remain_x)});
}
returnfalse;
}
publiclonghash(int[]state){
return(long)state[0]*1000001+state[1];
}
}
语言:
Java
classSolution{
publicbooleancanMeasureWater(intx,inty,intz){
if(x+yreturnfalse;
}
if(x==0||y==0){
returnz==0||x+y==z;
}
returnz%gcd(x,y)==0;
}
publicintgcd(intx,inty){
intremainder=x%y;
while(remainder!
=0){
x=y;
y=remainder;
remainder=x%y;
}
returny;
}
}
语言:
Java
importjava.util.ArrayList;
importjava.util.HashSet;
importjava.util.LinkedList;
importjava.util.List;
importjava.util.Objects;
importjava.util.Queue;
importjava.util.Set;
publicclassSolution{
publicbooleancanMeasureWater(intx,inty,intz){
//特判
if(z==0){
returntrue;
}
if(x+yreturnfalse;
}
StateinitState=newState(0,0);
//广度优先遍历使用队列
Queuequeue=newLinkedList<>();
Setvisited=newHashSet<>();
queue.offer(initState);
visited.add(initState);
while(!
queue.isEmpty()){
Statehead=queue.poll();
intcurX=head.getX();
intcurY=head.getY();
//curX+curY==z比较容易忽略
if(curX==z||curY==z||curX+curY==z){
returntrue;
}
//从当前状态获得所有可能的下一步的状态
ListnextStates=getNextStates(curX,curY,x,y);
//打开以便于观察,调试代码
//System.out.println(head+"=>"+nextStates);
for(StatenextState:
nextStates){
if(!
visited.contains(nextState)){
queue.offer(nextState);
//添加到队列以后,必须马上设置为已经访问,否则会出现死循环
visited.add(nextState);
}
}
}
returnfalse;
}
privateListgetNextStates(intcurX,intcurY,intx,inty){
//最多8个对象,防止动态数组扩容,不过Java默认的初始化容量肯定大于8个
ListnextStates=newArrayList<>(8);
//按理说应该先判断状态是否存在,再生成「状态」对象,这里为了阅读方便,一次生成8个对象
//以下两个状态,对应操作1
//外部加水,使得A满
StatenextState1=newState(x,curY);
//外部加水,使得B满
StatenextState2=newState(curX,y);
//以下两个状态,对应操作2
//把A清空
StatenextState3=newState(0,curY);
//把B清空
StatenextState4=newState(curX,0);
//以下四个状态,对应操作3
//从A到B,使得B满,A还有剩
StatenextState5=newState(curX-(y-curY),y);
//从A到B,此时A的水太少,A倒尽,B没有满
StatenextState6=newState(0,curX+curY);
//从B到A,使得A满,B还有剩余
StatenextState7=newState(x,curY-(x-curX));
//从B到A,此时B的水太少,B倒尽,A没有满
StatenextState8=newState(curX+curY,0);
//没有满的时候,才需要加水
if(curXnextStates.add(nextState1);
}
if(curYnextStates.add(nextState2);
}
//有水的时候,才需要倒掉
if(curX>0){
nextStates.add(nextState3);
}
if(curY>0){
nextStates.add(nextState4);
}
//有剩余才倒
if(curX-(y-curY)>0){
nextStates.add(nextState5);
}
if(curY-(x-curX)>0){
nextStates.add(nextState7);
}
//倒过去倒不满才倒
if(curX+curYnextStates.add(nextState6);
}
if(curX+curYnextStates.add(nextState8);
}
returnnextStates;
}
privateclassState{
privateintx;
privateinty;
publicState(intx,inty){
this.x=x;
this.y=y;
}
publicintgetX(){
returnx;
}
publicintgetY(){
returny;
}
@Override
publicStringtoString(){
return"State{"+
"x="+x+
",y="+y+
'}';
}
@Override
publicbooleanequals(Objecto){
if(this==o){
returntrue;
}
if(o==null||getClass()!
=o.getClass()){
returnfalse;
}
Statestate=(State)o;
returnx==state.x&&
y==state.y;
}
@Override
publicinthashCode(){
returnObjects.hash(x,y);
}
}
publicstaticvoidmain(String[]args){
Solutionsolution=newSolution();
intx=3;
inty=5;
intz=4;
//intx=2;
//inty=6;
//intz=5;
//intx=1;
//inty=2;
//intz=3;
booleanres=solution.canMeasureWater(x,y,z);
System.out.println(res);
}
}
语言:
php
classSolution{
/**
*@paramInteger$x
*@paramInteger$y
*@paramInteger$z
*@returnBoolean
*/
//贝祖定理
functioncanMeasureWater($x,$y,$z){
if($x+$y<$z)returnfalse;
if($x==0||$y==0)return$z==0||$x+$y==$z;
//x,y不为0,那么公约数$gcd最小为1,不需要判断为0
$gcd=$this->gcd($x,$y);
return($z%$gcd)==0?
true:
false;//比fmod快
}
//欧几里得算法
functiongcd($n,$m){
if(!
$m)return$n;
return$this->gcd($m,($n%$m));
}
}
语言:
go
funccanMeasureWater(xint,yint,zint)bool{
ifz==0||z==x+y{//条件1
returntrue
}elseifz>x+y||y==0{//条件2和3
returnfalse
}
//迭代公式2、4、6
returncanMeasureWater(y,x%y,z%y)
}
语言:
go
funccanMeasureWater(xint,yint,zint)bool{
for;z!
=0&&y!
=0&&z}
returnz==0||z==x+y
}
语言:
js
/**
*@param{number}x
*@param{number}y
*@param{number}z
*@return{boolean}
*/
varcanMeasureWater=function(x,y,z){
if(x+yif(z===0)returntrue;
if(x===0)returny===z;
if(y===0)returnx===z;
functionGCD(a,b){
letmin=Math.min(a,b);
while(min){
if(a%min===0&&b%min===0)returnmin;
min--;