leetcode第365题:水壶问题

有两个水壶,容量分别为 jug1Capacity 和 jug2Capacity 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 targetCapacity 升。

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

你可以:

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

示例 1:

输入: jug1Capacity = 3, jug2Capacity = 5, targetCapacity = 4
输出: true
解释:来自著名的 “Die Hard”

示例 2:

输入: jug1Capacity = 2, jug2Capacity = 6, targetCapacity = 5
输出: false

示例 3:

输入: jug1Capacity = 1, jug2Capacity = 2, targetCapacity = 3
输出: true

提示:

1 < = jug1Capacity, jug2Capacity, targetCapacity < = 106

方法一:深度优先搜索

思路及算法

首先对题目进行建模。观察题目可知,在任意一个时刻,此问题的状态可以由两个数字决定:X 壶中的水量,以及 Y 壶中的水量。

在任意一个时刻,我们可以且仅可以采取以下几种操作:

  • 把 X 壶的水灌进 Y 壶,直至灌满或倒空;
  • 把 Y 壶的水灌进 X 壶,直至灌满或倒空;
  • 把 X 壶灌满;
  • 把 Y 壶灌满;
  • 把 X 壶倒空;
  • 把 Y 壶倒空。

水壶问题是一个经典的数学问题,给定两个水壶的容量x和y,需要判断是否能够通过倒水的方式,将其中一个水壶中的水量准确地测量为z升。

代码中的_gen_states函数用于生成所有可能的状态。每个状态都是一个元组,表示两个水壶中的水量。函数中列举了六种可能的状态:

  • 清空A杯:将A杯中的水倒空,即(0, b)
  • 清空B杯:将B杯中的水倒空,即(a, 0)
  • 把A杯装满:将A杯装满,即(x, b)
  • 把B杯装满:将B杯装满,即(a, y)
  • 把A杯倒入B杯,直到B杯满:将A杯中的水倒入B杯,直到B杯满。如果倒入后A杯中的水量加上B杯中的水量小于B杯的容量,那么状态为(0, a + b),否则状态为(a + b - y, y)。
  • 把B杯倒入A杯,直到A杯满:将B杯中的水倒入A杯,直到A杯满。如果倒入后A杯中的水量加上B杯中的水量小于A杯的容量,那么状态为(a + b, 0),否则状态为(x, a + b - x)。

canMeasureWater函数使用BFS搜索状态空间,判断是否存在解。首先判断特殊情况,如果z小于0或者x和y的和小于z,那么肯定无法得到z升水量,直接返回False。然后使用队列q进行BFS,初始状态为0,表示两个水壶都是空的。使用集合visited记录已经访问过的状态,初始时将0加入visited。在BFS过程中,每次从队列中取出当前节点current_sum,如果current_sum等于z,那么找到了解,返回True。否则,根据current_sum生成下一层可能的状态,并判断是否已经访问过,如果没有访问过,则将其加入visited并加入队列q。如果遍历完所有可能的状态,仍然没有找到解,那么返回False。

在主函数中,创建了一个Solution对象sol,并分别调用了三个示例的测试用例。输出结果为True、False、True,分别表示第一个和第三个测试用例存在解,而第二个测试用例不存在解。

python

import math
import collections

# 生成所有可能的状态
def _gen_states(a, b, x, y):
    return [
        (0, b),  # 清空A杯
        (a, 0),  # 清空B杯
        (x, b),  # 把A杯装满
        (a, y),  # 把B杯装满
        (0, a + b) if a + b < y else (a + b - y, y),  # 把A杯倒入B杯,直到B杯满
        (a + b, 0) if a + b < x else (x, a + b - x)  # 把B杯倒入A杯,直到A杯满
    ]

class Solution(object):
    # 使用BFS搜索状态空间
    def canMeasureWater(self, x, y, z):
        if z < 0 or x + y < z:
            return False

        # 使用队列进行BFS
        q = collections.deque([0])
        visited = {0}

        while len(q):
            # 当前节点处理
            current_sum = q.popleft()
            if current_sum == z:
                return True

            # 生成下一层节点
            states = _gen_states(current_sum, y - current_sum, x, y)
            for state in states:
                if state not in visited:
                    visited.add(state)
                    q.append(sum(state))

        return False


if __name__ == '__main__':
    sol = Solution()
    print(sol.canMeasureWater(3, 5, 4))
    print(sol.canMeasureWater(1, 2, 3))
    print(sol.canMeasureWater(2, 6, 5))

方法二:数学法 - 最大公约数

思路

这是一道关于数论的题目,确切地说是关于裴蜀定理

摘自wiki的定义:
.
对任意两个整数 a、b,设 d是它们的最大公约数。那么关于未知数 x和 y的线性丢番图方程(称为裴蜀等式):
ax+by=m
.
有整数解 (x,y) 当且仅当 m是 d的整数倍。裴蜀等式有解时必然有无穷多个解。

因此这道题可以完全转化为裴蜀定理。还是以题目给的例子x = 3, y = 5, z = 4,我们其实可以表示成3 * 3 - 1 * 5 = 4, 即3 * x - 1 * y = z。我们用a和b分别表示3
升的水壶和5升的水壶。那么我们可以:

  • 倒满a(1)
  • 将a倒到b
  • 再次倒满a(2)
  • 再次将a倒到b(a这个时候还剩下1升)
  • 倒空b(-1)
  • 将剩下的1升倒到b
  • 将a倒满(3)
  • 将a倒到b
  • b此时正好是4升

上面的过程就是3 * x - 1 * y = z的具体过程解释。

也就是说我们只需要求出x和y的最大公约数d,并判断z是否是d的整数倍即可。

JavaScript

/**
 * @param {number} x
 * @param {number} y
 * @param {number} z
 * @return {boolean}
 */
var canMeasureWater = function(x, y, z) {
  if (x + y < z) return false;

  if (z === 0) return true;

  if (x === 0) return y === z;

  if (y === 0) return x === z;

  function GCD(a, b) {
    let min = Math.min(a, b);
    while (min) {
      if (a % min === 0 && b % min === 0) return min;
      min--;
    }
    return 1;
  }

  return z % GCD(x, y) === 0;
};

实际上求最大公约数还有更好的方式,比如辗转相除法:

def GCD(a, b):
    if b == 0: return a
    return GCD(b, a % b)

复杂度分析

  • 时间复杂度:O(log(max(a,b)))O(log(max(a, b)))O(log(max(a,b)))
  • 空间复杂度:空间复杂度取决于递归的深度,因此空间复杂度为 O(log(max(a,b)))O(log(max(a, b)))O(log(max(a,b)))。
  • 如果将上述过程改成迭代,那么可以降低到O(1)O(1)O(1),也不难

BFS、DFS模板

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/322309.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用composer构建软件包时文件(夹)权限设置

在构建软件包的时候你可能会需要对包源内文件或文件夹的权限做出相应的调整&#xff0c;以确保软件包在部署到客户端后可以正常运行。在此之前我们先来了解一下Apple文件系统内文件或文件夹的权限设定。 常见的文件或文件夹会有Owner, Group, Everyone这三种类型的所有权&#…

C++力扣题目108--有序数组转换为二叉平衡搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输…

数据结构学习 数位dp

关键词&#xff1a;数位dp 记忆化搜索 dfs 数位dp属于比较难的题目&#xff0c;所有数位dp在leetcode都是hard。 因为没有做出jz43.里面用到了数位dp&#xff0c;所以去学习了一下&#xff0c;学习看了这位大神的基础知识。 题目基本上是跟着这位灵大哥的题单做的。 学完数…

Hive分区表实战 - 多分区字段

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;创建学校数据库&#xff08;二&#xff09;创建省市分区的大学表&#xff08;三&#xff09;在本地创建数据文件1、创建四川成都学校数据文件2、创建四川泸州学校数据文件3、创建江苏南京学校数据文件4、创建江苏苏…

ubuntu打开epub格式的文件

Koodo Reader 是一个开源免费的电子书阅读器&#xff0c;支持多达15种主流电子书格式&#xff0c; 内置笔记、高亮、翻译功能&#xff0c;助力高效书籍阅读和学习。 官网地址 拖拽到此处即可添加图书 支持滚轮和点击翻页 菜单在这里 可以记笔记 查看笔记

大数据开发之Hive(压缩和存储)

第 9 章&#xff1a;压缩和存储 Hive不会强制要求将数据转换成特定的格式才能使用。利用Hadoop的InputFormat API可以从不同数据源读取数据&#xff0c;使用OutputFormat API可以将数据写成不同的格式输出。 对数据进行压缩虽然会增加额外的CPU开销&#xff0c;但是会节约客观…

CTFhub-phpinfo

CTFhub-Web-信息泄露-“phpinfo” 题目信息 解题过程 ctrlF搜索关键字…

【Linux驱动】设备树中指定中断 | 驱动中获得中断 | 按键中断实验

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux驱动》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3c0;在设备树中指定中断&#x1f3c0;代码中获得中断&#x1f3c0;按键中断⚽驱动…

Python教程79:关于海龟画图,Turtle模块需要学习的知识点

1.海龟画图的基本步骤&#xff1a;A-B-C-D-E-F A.导入turtle模块&#xff1a;首先需要导入Python中的turtle模块&#xff0c;该模块提供了海龟绘图所需的基本函数和属性。 import turtle as tB.设置画布大小 使用turtle.screensize()函数。该函数可以设置画布的宽度高度背景…

中小企业如何做好信息化规划?

中小企业需不需要做信息化规划&#xff1f;什么时候做信息化规划比较好&#xff1f; 企业的信息化规划&#xff0c;一定是越早越好&#xff0c;越快越好。 因为信息化是一个过程&#xff0c;不是一个结果&#xff0c;它不是一天完成的事情&#xff0c;而是贯穿着企业经营管理…

FPGA引脚 Bank认知--FPGA 选型的一些常识

关键字 HP I/O Banks, High performance The HP I/O banks are deisgned to meet the performance requirements of high-speed memory and other chip-to-chip interface with voltages up to 1.8V. HR I/O Banks, High Range The HR I/O banks are designed to support a wid…

用python提取PDF中各类文本内容的方法

从PDF文档中提取信息&#xff0c;是很多类似RAG这样的应用第一步要处理的事情&#xff0c;这里需要做好三件事&#xff1a; 提取出来的文本要保持信息完整性&#xff0c;也就是准确性提出的结果需要有附加信息&#xff0c;也就是要保存元数据提取过程要完成自动化&#xff0c;…

FPGA四选一的多路选择器(用三元运算符?:解决)

一. 三元运算符? :用法 ?:符号通常用于条件运算符&#xff0c;表示条件判断。它类似于C语言中的三元运算符&#xff0c;用于根据条件选择不同的操作或值。 例如&#xff0c;在Verilog中&#xff0c;条件运算符?:可以用于if-else语句的简写形式。它的一般语法格式如下&#x…

市场复盘总结 20240113

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 昨日主题投资 连板进级率 100% 二进三&#xff1a; 进级率低 14% 最常用的二种方法&#xff1a; 方法一&a…

IIC学习之SHT30温湿度传感器(基于STM32)

简介 附上SHT30资料和逻辑分析仪源文件&#xff0c;点击下载 关于IIC的介绍网上已经非常详尽&#xff0c;这里只说重点&#xff1a; 双线&#xff08;SDA&#xff0c;SCL&#xff09;&#xff0c;半双工采用主从结构&#xff0c;支持一主多从&#xff0c;通过地址寻址&#…

Hologres + Flink 流式湖仓建设

Hologres Flink 流式湖仓建设 1 Flink Hologres2 实时维表 Lookup 1 Flink Hologres holo在实时数仓领域非常受欢迎&#xff0c;一般搭配flinkhologres来做实时数仓&#xff0c;中间分层用holo&#xff0c;上下游一般依赖于holo的binlog来下发数据 2 实时维表 Lookup Holo…

生活的再思考,写在开篇

近几年的就业行情很特别&#xff0c;特别是对中年人&#xff0c;早先网络上主流的声音是动不动总包百万&#xff0c;手握几个 Offer &#xff0c;纠结应该去哪里。现在的主流声音变成了&#xff0c;被毕业优化掉后几个月都没找到合适的工作&#xff0c;焦虑迷茫无所适从&#x…

药物“出气”可知|ZL-005大小鼠雾化给药仪

雾化吸入给药是一种通过装置使药物进入肺部局部或全身发挥作用的给药方式。相较于口服药剂&#xff0c;雾化吸入给药可避免首过效应和药剂破坏&#xff0c;提高药物生物利用度。 而ZL-005大小鼠雾化给药仪&#xff0c;则是新一代小动物雾化装置的理想选择&#xff0c;可完成动…

你升级GPT-4了吗?,如何申请GPT-4 API?最全攻略

ChatGPT4就是ChatGPTPlus&#xff0c;调用接口就分ChatGPT3.5与ChatGPT4.0&#xff0c;如果你想使用ChatGPT4的接口就先充值ChatGPTPlus&#xff0c;在区ChatGPT绑定API即可调用4.0的API 在国内很多小伙伴还不知道怎么升级ChatGPT-4&#xff0c;因为自己只有国内的卡&#xff…

春晚为什么失去了观众?

​春晚失去了观众&#xff0c;这是近年来不可忽视的现象。春晚作为中国的一项传统文化活动&#xff0c;曾经吸引了亿万观众的眼球&#xff0c;但如今却面临着越来越多的挑战和质疑。那么&#xff0c;春晚为什么失去了观众呢&#xff1f; 首先&#xff0c;随着时代的变迁&#…