DFS/BFS 系列:LC 365 水壶问题

方法1:BFS,C++版本写起来很繁琐,Python很简洁 

using PII = pair<int, int>; //分别是x, y中的水量,作为状态量

class Solution {
public:
    PII op(int index, const PII& cur, int x, int y) {
        switch (index) {
            case 0: return make_pair(cur.first, 0);
            case 1: return make_pair(cur.first, y);
            case 2: return make_pair(0, cur.second);
            case 3: return make_pair(x, cur.second);
            case 4: 
                if(cur.first + cur.second > x)
                    return make_pair(x, cur.first + cur.second - x);
                else
                    return make_pair(cur.first + cur.second, 0);
            case 5:
                if(cur.first + cur.second > y)
                    return make_pair(cur.first + cur.second - y, y);
                else
                    return make_pair(0, cur.first + cur.second);
        }
        return make_pair(0, 0);
    }

    bool canMeasureWater(int x, int y, int z) {
        //BFS依赖一个队列,初始起点为(0,0)
        deque<PII> que;
        que.emplace_back(make_pair(0, 0));
        //哈希表存储访问过的节点
        auto hash_func = [](const PII& o) {return hash<int>()(o.first) ^ hash<int>()(o.second); };
        unordered_set<PII, decltype(hash_func)> visited(0, hash_func);

        while(!que.empty()) {
            PII cur = que.front(); 
            que.pop_front();

            auto [remain_x, remain_y] = cur;
            if(remain_x==z || remain_y==z || remain_x+remain_y==z) {
                return true;
            }
            //BFS:访问当前节点周围的6个节点
            for(int i = 0; i < 6; i++) {
                PII temp = op(i, cur, x, y);
                if(!visited.count(temp)) {
                    visited.emplace(temp);
                    que.emplace_back(temp);
                }
            }
        }
        return false;
    }
};
class Solution:
    def canMeasureWater(self, x: int, y: int, z: int) -> bool:
        from collections import deque
        que = deque()
        que.append((0, 0))
        visited = set()
        visited.add((0, 0))

        while que:
            cur_x, cur_y = que.popleft();
            if cur_x == z or cur_y == z or cur_x + cur_y == z:
                return True
            for (nb_x, nb_y) in ((cur_x, 0), (cur_x, y), (0, cur_y), (x, cur_y), \
                                (x, cur_x+cur_y-x) if cur_x+cur_y > x else (cur_x+cur_y, 0), \
                                (cur_x+cur_y-y, y) if cur_x+cur_y > y else (0, cur_x+cur_y)):
                if (nb_x, nb_y) not in visited:
                    visited.add((nb_x, nb_y))
                    que.append((nb_x, nb_y)) 
        return False

方法2:DFS

最大的区别在于visited的处理, 对于没有visited过的节点的临近节点再压入栈,这才符合DFS的思想。

Bug1:for循环放在了if语句的外面。Bug2:visited一开始把原始节点标记为访问,就无法进行DFS了

class Solution:
    def canMeasureWater(self, x: int, y: int, z: int) -> bool:
        stack = []
        stack.append((0, 0))
        visited = set()
        # visited.add((0, 0))

        while stack:
            cur_x, cur_y = stack.pop()
            if cur_x == z or cur_y == z or cur_x + cur_y == z:
                return True
            if (cur_x, cur_y) not in visited:
                visited.add((cur_x, cur_y))
                for (nb_x, nb_y) in ((cur_x, 0), (cur_x, y), (0, cur_y), (x, cur_y), \
                                    (x, cur_x+cur_y-x) if cur_x+cur_y > x else (cur_x+cur_y, 0), \
                                    (cur_x+cur_y-y, y) if cur_x+cur_y > y else (0, cur_x+cur_y)):
                    stack.append((nb_x, nb_y))
        return False

递归写法,会因为递归层数太深报错:

class Solution:
    def canMeasureWater(self, x: int, y: int, z: int) -> bool:
        # import sys
        # sys.setrecursionlimit(100000)#设置最大递归次数
        visited = set()
        def DFS(cur_x, cur_y):
            if cur_x == z or cur_y == z or cur_x + cur_y == z:
                return True
            if (cur_x, cur_y) not in visited:
                visited.add((cur_x, cur_y))
            for (nb_x, nb_y) in ((cur_x, 0), (cur_x, y), (0, cur_y), (x, cur_y), \
                                    (x, cur_x+cur_y-x) if cur_x+cur_y > x else (cur_x+cur_y, 0), \
                                    (cur_x+cur_y-y, y) if cur_x+cur_y > y else (0, cur_x+cur_y)):
                if (nb_x, nb_y) not in visited:
                    visited.add((nb_x, nb_y))
                    if DFS(nb_x, nb_y):
                        return True
                    visited.remove((nb_x, nb_y))
            return False
        return DFS(x, y)

方法3:贝祖定理

class Solution {
public:
    bool canMeasureWater(int x, int y, int z) {
        if(z == 0) return true;
        if(x+y < z) return false;
        if(x==0 || y==0) return (x+y==z);
        return z % gcd(x, y) == 0;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值