365. 水壶问题

思路:刚看这题是懵圈的状态的,完全不知道如何入手。但是仔细想想会发现这是一个搜索问题。抽象出来的话,就是你有两个容器,你需要用这两个容器凑出“一定容量”的水。允许的操作有3个,如题中所述,实际上是有6个操作的。这就是回到了递归执行可执行操作,然后寻找结束条件这类的问题了,最容易想到的就是DFS算法或BFS算法。
/**6种操作1. 装满水壶12. 装满水壶23. 清空水壶14. 清空水壶25. 水壶1倒向水壶2,直到水壶2满或水壶1倒尽了6. 水壶2倒向水壶1,直到水壶1满或水壶2倒尽了结束条件水壶1凑出 || 水壶2凑出 || 水壶1+水壶2凑出*/class Solution {public boolean canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {int x = jug1Capacity;int y = jug2Capacity;int z = targetCapacity;LinkedList<int[]> stack = new LinkedList<>(); //装水壶1和水壶2的当前水量stack.addLast(new int[]{0, 0});Set<Long> visited = new HashSet(); //已经查过了,使用hash函数while (!stack.isEmpty()) {if (visited.contains(hash(stack.getLast()))) {stack.pollLast();continue;}visited.add(hash(stack.getLast()));int[] state = stack.pollLast();int remainX = state[0];int remainY = state[1];if (remainX==z || remainY==z || (remainX+remainY)==z) {return true;}//上述6种操作stack.push(new int[]{x, remainY});stack.push(new int[]{remainX, y});stack.push(new int[]{0, remainY});stack.push(new int[]{remainX, 0});int xToy = Math.min(remainX,y-remainY);stack.push(new int[]{remainX - xToy, remainY + xToy});int yTox = Math.min(x-remainX,remainY);stack.push(new int[]{remainX + yTox, y - yTox});}return false;}public long hash(int[] state) {return (long) state[0] * 10000001 + state[1];}}
