LeetCode 31.水壶问题 数学方法与广度遍历

题目描述

有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?

如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。

你允许:

  • 装满任意一个水壶
  • 清空任意一个水壶
  • 从一个水壶向另外一个水壶倒水,直到装满或者倒空

示例 1: (From the famous "Die Hard" example)

输入: x = 3, y = 5, z = 4
输出: True

示例 2:

输入: x = 2, y = 6, z = 5
输出: False

解题思路

数学方法:找到x,y的最大公约数能否z被整除

BFS:将水壶x,y的相关操作分解为6个状态,分别为 // 1.给x装满水 // 2.给y装满水 // 3.清空x的水 // 4.清空y的水 // 5.x向y倒水,直到x空或者y满 // 6.y向x倒水,直到y空或者x满 // 通过不断的搜索,如果x,y中的水满足 // x == z || y == z || x + y == z 返回true,否则继续搜索直到所有情况都搜索完毕

代码如下

数学方法:

public boolean canMeasureWater(int x, int y, int z) {
           if(x+y<z){
                return false;
            }
            if(x == 0 || y == 0){
                return z==0 || x+y==z;
            }
            return z % gcb(x,y) == 0;
        }
        int gcb(int m, int n) {
                if (m < n) {// 保证m>n,若m<n,则进行数据交换
                    int temp = m;
                    m = n;
                    n = temp;
                }
                if (m % n == 0) {// 若余数为0,返回最大公约数
                    return n;
                } else { // 否则,进行递归,把n赋给m,把余数赋给n
                    return gcb(n, m % n);
                } 

        }

BFS:

public boolean canMeasureWater(int x, int y, int z) {

        if (z > x + y) return false;
        if (x == z || y == z || x + y == z) return true;

        // 保存搜索过的情况,防止无止境的搜索下去
        Set<List<Integer>> set = new HashSet<>();

        // 保存每次操作后,x,y中剩余的水的容量
        LinkedList<List<Integer>> res = new LinkedList<>();

        // 初始时,x y中均没有水
        List<Integer> list = Arrays.asList(0, 0);
        set.add(list);
        res.add(list);

        while (!res.isEmpty()) {
            List<Integer> poll = res.poll();
            int remain_x = poll.get(0);
            int remain_y = poll.get(1);
            if (remain_x == z || remain_y == z || remain_x + remain_y == z) {
                return true;
            }

            // 给x加满水
            List<Integer> p1 = Arrays.asList(x, remain_y);
            if (!set.contains(p1)) {
                set.add(p1);
                res.add(p1);
            }

            // 给y加满水
            List<Integer> p2 = Arrays.asList(remain_x, y);
            if (!set.contains(p2)) {
                set.add(p2);
                res.add(p2);
            }

            // 清空x的水
            List<Integer> p3 = Arrays.asList(0, remain_y);
            if (!set.contains(p3)) {
                set.add(p3);
                res.add(p3);
            }

            // 清空y的水
            List<Integer> p4 = Arrays.asList(remain_x, 0);
            if (!set.contains(p4)) {
                set.add(p4);
                res.add(p4);
            }

            // x向y倒水
            int tmp_x = (remain_x + remain_y) <= y ? 0 : remain_x + remain_y - y;
            int tmp_y = (remain_x + remain_y) < y ? remain_x + remain_y : y;
            List<Integer> p5 = Arrays.asList(tmp_x, tmp_y);
            if (!set.contains(p5)) {
                set.add(p5);
                res.add(p5);
            }

            // y向x倒水
            tmp_y = (remain_x + remain_y) <= x ? 0 : remain_x + remain_y - x;
            tmp_x = (remain_x + remain_y) < x ? remain_x + remain_y : x;
            List<Integer> p6 = Arrays.asList(tmp_x, tmp_y);
            if (!set.contains(p6)) {
                set.add(p6);
                res.add(p6);
            }

        }

        return false;
    }参考自:LeetCode用户yw-git


原文地址:https://www.cnblogs.com/Transkai/p/12539705.html

时间: 2024-11-13 06:56:59

LeetCode 31.水壶问题 数学方法与广度遍历的相关文章

zznu 1255 数字统计(数位DP, 数学方法)

最近在学数位DP, 感觉还是满有收获的! 做了几个题之后想起来自己OJ上曾经做的一道题,以前是用数学方法写的,现在改用数位DP来写了一遍. 题目: 1255: 数字统计 时间限制: 1 Sec  内存限制: 128 MB提交: 31  解决: 4[提交][状态] 题目描述 一本书的页码从自然数1 开始顺序编码直到自然数n.书的页码按照通常的习惯编排, 每个页码都不含多余的前导数字0.例如,第6 页用数字6 表示,而不是06 或006 等.数 字计数问题要求对给定书的总页码n,计算出书的全部页码中

[array] leetcode - 31. Next Permutation - Medium

leetcode - 31. Next Permutation - Medium descrition Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible

去掉有序数组中重复数字 原地 leetcode java (最简单的方法)

1.利用荷兰国旗的思路,每次记住最后一个位置,遇到一个不重复的数,放在它后面,代码很简单. Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this in place with consta

图像处理数学方法

图像处理数学方法 在图像处理的发展过程中,数学始终起着举足轻重的作用,并渗透在图像处理的所有分支之中. 到上世纪六七十年代为止,以Fourier分析为代表的线性处理方法占据了几乎整 个数字图像处理领域.在此期间,借助于随机过程理论,人们建立了图像模型通过概率论以及在此基础上建立的信息论建立了图像编码的框架:线性滤波(维纳滤 波.卡尔曼滤波)方法为低层图像处理提供了有力的理论支持:而FFT则被广泛使用在图像处理的几乎所有分支中.这些数学工具极大地促进了图像处理的发展和 应用. 自上世纪八十年代开始

Javascript中,数学方法可以分成以下几类: constans(常数)、power functions(乘方函数)、trigonometic functions(三角函数)、rounding functions(舍入函数)、random numbers(随机数字)

在Javascript中,数学方法可以分成以下几类: constans(常数).power functions(乘方函数).trigonometic functions(三角函数).rounding functions(舍入函数).random numbers(随机数字) 常数和乘方函数 Math.E 自然对数的底(为常数) 2.718 Math.LN10 10的自然对数 2.302 Math.LN2 2的自然对数 0.693 Math.PI 圆周率 3.1415 Math.SQRT1_2 1/

数学方法

数学方法即用数学语言表述事物的状态.关系和过程,并加以推导.演算和分析,以形成对问题的解释.判断和预言的方法.所谓方法,是指人们为了达到某种目的而采取的手段.途径和行为方式中所包含的可操作的规则或模式.人们通过长期的实践,发现了许多运用数学思想的手段.门路或程序.同一手段.门路或程序被重复运用了多次,并且都达到了预期的目的,就成为数学方法.数学方法是以数学为工具进行科学研究的方法,即用数学语言表达事物的状态.关系和过程,经过推导.运算与分析,以形成解释.判断和预言的方法. 数学方法具有以下三个基

常见的数学方法

1.怎么让数字保留n位小数? 数字.toFixed(n); var num = 123.567;   num.toFixed(2); 2.将字符串转化为数字的方法有哪些? 数学方法有哪些?(Math) var str = '123.45'; parseInt(str); parseFloat(str); Number(str); 3. 随机数:Math.random()  0-1之间:求10到20之间的随机数随机数即:10+Math.random()*20 4.  向上取整: Math.ceil

Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)

Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理) 题目描述 一条报文包含字母A-Z,使用下面的字母-数字映射进行解码 'A' -> 1 'B' -> 2 ... 'Z' -> 26 给一串包含数字的加密报文,求有多少种解码方式 举个例子,已知报文"12",它可以解码为AB(1 2),也可以是L (12) 所以解码方式有2种. 测试样例 Input: "0" "121212" "1010

#8 Python数学方法

前言 前几节了解了Python的不同数据类型,有小伙伴会问,不同的数据类型之间是否可以相互转换?肯定是可以的,本篇博文主要记录数字类型的转换,其他类型的相互转换会在下几节记录,Here we go! 一.Python数字类型转换 通过前几节,我们知道Python数字的数据类型有:整型.长整型.浮点型.和复数,它们之间是如何转换的呢?亦或者它们是如何转换为其他数据类型呢?先来看所有的方法: int(x [,base ]) # 将 x 转换为一个整数 float(x ) # 将 x 转换到一个浮点数