365. 水壶问题

原题链接:

365. 水壶问题

https://leetcode.cn/problems/water-and-jug-problem/description/

完成情况:

在这里插入图片描述

解题思路:

这段代码是一个解决水壶问题的解决方案。给定两个水壶的容量x和y,以及目标z,判断是否可以通过操作水壶来得到z升的水。代码中使用了一个栈来模拟操作过程,同时使用一个哈希集合来记录已经遍历过的状态,避免重复计算。

在主要的canMeasureWater方法中,首先将初始状态(0,0)入栈,然后进行循环直到栈为空。在每次循环中,首先判断当前状态是否已经遍历过,如果是则弹出栈顶并继续下一次循环。然后将当前状态弹出栈,并判断是否满足目标条件,如果是则返回true。接着按照题目要求依次模拟六种操作,并将新状态入栈。

hash方法用于将状态数组转换成一个长整型的哈希值,用于在哈希集合中存储和比较状态。

参考代码:

package leetcode板块;

import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

public class _365水壶问题_情况探讨_dfs {
    /**
     *
     * @param x
     * @param y
     * @param target
     * @return
     */
    public boolean canMeasureWater(int x, int y, int target) {
        /*
        有两个水壶,容量分别为 x 和 y 升。
        你可以:
            1.装满任意一个水壶
            2.清空任意一个水壶
            3.将水从一个水壶倒入另一个水壶,直到接水壶已满,或倒水壶已空。
         TODO 那么这道题就是遍历所有的情况,并判断能否产生需要的求解
         */
        Deque<int []> myStack = new LinkedList<int []>();
        myStack.push(new int[]{0,0});
        Set<Long> canFind = new HashSet<Long>();    //记录能够产生的所有元素
        while (!myStack.isEmpty()){
            if (canFind.contains(mapToHash(myStack.peek()))){
                //说明本次的迭代会进入循环
                myStack.pop();
                continue;
            }
            //寻找没有遇到过的组合数
            canFind.add(mapToHash(myStack.peek()));
            int [] curElements = myStack.pop();     //栈里面每一个都是一个数组,用于记录两个水壶的当前量
            int remind_X = curElements[0],remind_y = curElements[1];
            //判断当前的所有组合情况,并将所有组合结果保存到栈中
            if (remind_X == target || remind_y == target || remind_X + remind_y == target){
                return true;
            }
            //----------将上述相互灌水壶的各种结果值保存在栈中--------------------------------------
                //将x灌满
            myStack.push(new int[]{x,remind_y});
                //将y灌满
            myStack.push(new int[]{remind_X,y});
                //将x倒空
            myStack.push(new int[]{0,remind_y});
                //将y倒空
            myStack.push(new int[]{remind_X,0});
                //将x的水全部倒入y中,直到遇到灌满或倒空。
            myStack.push(new int[]{remind_X - Math.min(remind_X,y - remind_y),remind_y + Math.min(remind_X,y-remind_y)});
                //将y的水全部倒入x中,直到遇到灌满或倒空。
            myStack.push(new int[]{remind_X + Math.min(remind_y,x - remind_X),remind_y - Math.min(remind_y,x-remind_X)});
        }
        return false;
    }

    /**
     * 防止计算超时,将所有的数都有使用到curElements[0]和curElements[1]去隐射到hash上
     * @param curElements
     * @return
     */
    private Long mapToHash(int[] curElements) {
        //return (long)curElements[0]*1000001 + curElements[1];
        //1 <= x, y, target <= 10^3
        return Long.valueOf(curElements[0]*1000002 + curElements[1]);
    }

}

错误经验吸取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值