当前位置: 首页 > news >正文

算法:双指针

算法:双指针

    • 双指针
    • 快慢指针
    • 对撞指针
    • 总结


双指针

LeetCode 283.移动零

在这里插入图片描述

以上题目要求我们把所有0移动到数组的末尾,也就是说,我们要把数组转化为以下状态:

[ 非0区域 ] [ 0区域 ]

像这种把一个数组划分为多个区域的题型,就是数组划分。而数组划分非常适合使用双指针算法

对于这道题,我们可以用两个指针,对数组进行动态的区域划分。

在这里插入图片描述

其中dest指针维护一段区域,表示非0区域cur指针与dest之间的区域是0区域。而cur后面的区域是待处理区域

也就是我们的数组被划分为了以下情况:

[ 非0区域 ] [ 0区域 ] [ 待处理区域 ]

当我们的cur移动后,对于一个新的数据,就要根据条件来决定把它放到哪一个区域去。当cur指针走到末尾,数组就被处理为了:

[ 非0区域 ] [ 0区域 ]

也就是题目要求的样子了。

对于本题而言,如果新插入的数据是0,那就放到cur维护的区域里面,此时直接cur++即可;如果新插入的数据是非0,那么就放到dest的末尾,为了保证dest不会覆盖掉cur原本维护的0,因此要进行一个交换操作。

在这里插入图片描述

代码如下:

class Solution
{
public:void moveZeroes(vector<int>& nums) {int dest = -1;int cur = 0;int sz = nums.size();while (cur < sz){if (nums[cur])swap(nums[++dest], nums[cur]);cur++;}}
};

LeetCode 75.颜色分类

在这里插入图片描述

这一题也是一个区域划分问题,根据上一题的思路,我们可以把数组划分为以下状态:

[ 0区域 ] [ 1区域 ] [ 2区域 ]

相比于上一题,这次我们要划分出三个区域来,毫无疑问就需要更多的指针来维护区域,大致可以划分为:

[ 0区域 ] [ 1区域 ] [ 待处理 ] [ 2区域 ]

我们让维护0区域的指针left向右拓展,维护2区域的指针right向左拓展,以及利用cur指针向右遍历数组:

在这里插入图片描述

上图中,left指针左侧维护了一段0区域leftcur之间维护了一段1区域curright之间是待处理区域,right右侧是2区域。当cur往后遍历,如果遇到一个新的数据,就要决定把它放到哪一个区域去:

  1. 遇到0,就交换++leftcur的值,把0放到left后面一位,拓展left指针维护的区域
  2. 遇到1,就直接++cur,把1放到curleft之间
  3. 遇到2,就交换--rightcur的值,把2放到right的前面一位,拓展right维护的区域

要注意的是,当把0交给left后,cur++;但是当把2交给right后,cur不能移动。因为left后面的一位数一定是符合cur范围要求的,也就是区间(left, cur]之间的数据被交换到了cur的位置,此时不用判断被交换过来的数据。而right的前面一位数据是不确定的,也就是把区间(cur, right)之间的数据,交换给了cur。而(cur, right)之间的数据是待处理的不确定数据,因此还需要额外判断一次。比如上图中,right的前一位数据就是0,交换后状态如下:

在这里插入图片描述

可以看到,cur得到的数据是0,应该被放到left维护的区域去。

总代码如下:

class Solution
{
public:void sortColors(vector<int>& nums){int left = -1;int right = nums.size();int cur = 0;while (cur < right){if (nums[cur] == 0)swap(nums[++left], nums[cur++]);else if (nums[cur] == 2)swap(nums[--right], nums[cur]);//交换后不能cur++,进入下一轮循环在判断一次cur的值elsecur++;}}
};

快慢指针

LeetCode 202.快乐数

在这里插入图片描述

该题的意思是,每个数字的下一个数字是该数字所有位的平方和,比如 19 的下一位数字就是 1 2 + 9 2 = 82 1^{2} + 9^{2} = 82 12+92=82。一直以这个规则操作下去,会出现两种情况:

  1. 最后该数字变为1,那么该数字是快乐数
  2. 该数字陷入死循环,那么该数字不是快乐数
  • 比如19 -> 82 -> 68 -> 100 -> 1 ,最后19变成了1,所以19是一个快乐数
  • 比如2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4,可以发现其陷入了一个死循环,从4开始又以4结束,那么2就不是一个快乐数

这题的难点不在于如何计算下一位快乐数字,而在于如何判断一个数字陷入了死循环

对于这种循环问题,就可以使用快慢指针

快慢指针规则如下:

  1. 定义两个变量fastslow
  2. fast2步,slow走一步
  3. 如果fast走到终点,说明没有循环
  4. 如果fastslow相遇,说明陷入了循环

一开始fastslow都在起点:

在这里插入图片描述

fast走两步,slow走一步:

在这里插入图片描述

由于这是一个循环结构,当fast进入第二圈循环,slow还没有走完第一圈:

在这里插入图片描述

这个时候,由于slow的速度为1fast的速度为2,那么每次行动fastslow的距离就会缩短1,最后fast一定可以遇到slow

在这里插入图片描述

此时两者相遇,说明这是一个循环结构

因此代码逻辑如下:

  1. 定义两个变量,fastslowfast走两步,slow走一步
  2. 如果fast变成1,那么该数字是快乐数,返回true
  3. 如果fastslow相遇,那么有循环结构,该数字不是快乐数,返回false

代码如下:

class Solution 
{
public:int getNextNum(int n) //到下一个数字的函数{int num = 0;while (n){int tmp = n % 10;num += tmp * tmp;n /= 10;}return num;}bool isHappy(int n) {int fast = n;int slow = n;while (fast != 1){fast = getNextNum(getNextNum(fast));//fast走两步slow = getNextNum(slow);//slow走一步if (fast == slow && fast != 1)//两者相遇,有循环return false;} return true;//到这里说明fast = 1,是快乐数}
};

其中有一个注意点,就是条件fast == slow && fast != 1,这里一种情况就是fast虽然和slow相等,但是两者都为1,此时是快乐数。

比如数字1010 -> 1 -> 1slow走第一步就是1了,fast走两步也是1,此时两者相等。


LeetCode 141.环形链表

在这里插入图片描述

本题要求判断一个链表中有没有环结构,那就是一个循环问题,要使用快慢指针

我们刚刚已经讲解过快慢指针了,现在我们直接说明代码逻辑:

  1. 定义两个指针fastslowfast走两步,slow走一步
  2. 如果fastnullptr,说明链表无环,返回true
  3. 如果fastslow相遇,说明有环,返回false

代码如下:

class Solution {
public:bool hasCycle(ListNode* head){ListNode* slow = head;ListNode* fast = head;while (fast && fast->next){fast = fast->next->next;slow = slow->next;if (fast == slow)return true;}return false;}
};

注意事项:

  1. 进入循环时,因为fast要走两步,因此要判断fast->next是不是空指针,否则fast->next-->next就是访问空指针行为

LeetCode 142.环形链表II

在这里插入图片描述

这道题要求我们求出环形链表的环入口,这就麻烦了,通过之前的fastslow的快慢指针追击问题,我们已经可以判断是否存在环结构了,那么我们要如何求环入口呢?

看到以下示意图:

在这里插入图片描述

现在slowfast刚好相遇,参数含义如下:

L:从起点到环入口的距离
C:环周长
X:相遇点和环入口的距离

由于fast的速度是slow的两倍,当slow走的距离是L + X,因此此时fast走了2(L + X)的距离。

又由于fast一定经过了起点到入口的L距离,因此此时fast在环中走了2(L + X) - L = L + 2X的距离。

假设fast已经在环中转了n圈,因此此时fast在环中走了nC + X的距离

那么可以列出公式:

n C + X = L + 2 X nC + X = L + 2X nC+X=L+2X

变形得到:

n C − X = L \mathbf{{\color{Red} nC - X = L} } nCX=L

这个公式具有重大意义,L代表起点到入口的距离,nC代表n个环周长,X代表当前相遇点与入口的距离。

nC -X整体可以看成(n - 1)C + (C - X)C - X就代表相遇点开始与环入口的优弧的长度

此时如果让一个指针A从起点开始走L的距离所用的时间,和让一个指针B从相遇点开始走n - 1圈外加一个C - X的距离所用的时间是一致的。由于相遇点与环入口距离已经是X了,那么指针B最后刚好会走到环入口。而指针A从入口开始走L到达的地方也是环入口,因此两者相遇!

通过这个公式可知:让一个指针从起点开始走,一个指针从相遇点开始走,两者会在环入口相遇

因此我们的代码逻辑如下:

  1. 定义两个指针fastslowfast走两步,slow走一步
  2. 如果fastnullptr,说明链表无环,返回nullptr
  3. 如果fastslow相遇,说明有环,开始找环入口
  • 在相遇点定义一个指针B,也就是B = slow;在起点定义一个指针A,也就是A = head
  • 两个指针各自行动,速度一致,最后AB相遇的地方就是环入口
  • 返回AB

代码如下:

class Solution
{
public:ListNode* detectCycle(ListNode* head){ListNode* fast = head;ListNode* slow = head;while (fast && fast->next){fast = fast->next->next;slow = slow->next;if (slow == fast)  // 有环,开始找入口{ListNode* A = head;ListNode* B = slow;while (A != B)//A与B相遇点,就是环入口{A = A->next;B = B->next;}return A;}}return nullptr; //没有环,返回空指针}
};


对撞指针

LCR 179.查找总价格为目标值的两个商品

在这里插入图片描述

这道题给了一个升序数组,要求我们求出数组中任意两个值的和刚好为target

该数组有一个特点:有序数组。像这种在一个有序区间中查找两个元素,计算得到固定值的题型,就可以使用对撞指针

如果我们直接暴力解法的话,那就是枚举所有两两一对的元素组,直到某一对刚好和为target,时间复杂度为 O ( N 2 ) O(N^{2}) O(N2)

假设现在的数组为[8, 21, 27, 34, 52]target = 61

因为数组具有单调性,我们可以一开始就枚举最左侧和左右侧的两个元素

在这里插入图片描述

当前8 + 52 = 6061小,说明我们需要一个更大的值来增大当前总和。那么由于数组升序,我们只需要left++即可:

在这里插入图片描述

当前21 + 52 = 7361大,说明我们需要一个更小的值来缩小当前总和。那么由于数组升序,我们只需要right--即可:

在这里插入图片描述

当前21 + 34 = 5561小,说明我们需要一个更大的值来增大当前总和。那么由于数组升序,我们只需要left++即可:

在这里插入图片描述

当前27 + 34 = 61,我们就找到了目标值,返回leftright下标即可。

正是由于数组单调性,我们可以通过比大小来进行指针的调整,来决定当前总值要变大还是变小,如果最后leftright相遇了,说明不存在这样的和。

为什么可以这样优化呢?看到这个例子:

在这里插入图片描述
对于34而言,其要去枚举除了自己以外的所有值,但是当前21 + 34 = 5561小,如果把21改为8,那只总和只会更小,因此我们只需要再枚举比21大的值即可。也就是通过单调性,免去了很多不必要的枚举行为

代码如下:

class Solution 
{
public:vector<int> twoSum(vector<int>& price, int target){int left = 0;int right = price.size() - 1;while (left < right){if (price[left] + price[right] > target) //和比target大,right--right--;else if (price[left] + price[right] < target) //和比target小,left++left++;elsereturn { price[left], price[right] };}return { 0, 0 };}
};

LeetCode 11.盛水最多的容器

在这里插入图片描述

本题要求存储的最大水量,其实也就是两个下标之间的距离right - leftmin(height[left], height[right])的乘积。

如果暴力枚举,那么就是枚举出每一对下标,然后求出最大面积,时间复杂度为 O ( N 2 ) O(N^{2}) O(N2)

本题也可以使用双指针的算法,水量的值与right - leftmin(height[left], height[right])两个变量正相关,如果我们利用两个指针向内枚举,那么right - left这个值是一直在减小的,也就是有一项有单调性

对于这种,如果利用对撞指针下标向内枚举,对组成结果的某一项变量的影响是单调的,就可以考虑对撞指针

假设我们已经在边界上定义好了leftright指针:

在这里插入图片描述

第一个问题就是,应该以什么规则进行向内移动指针?

移动的过程中,水的宽度的一直递减的,那么我们就要尽可能找到height高的元素,来拔高水量。

比如说当前的两个高度为37,由于水的高度取决于较低的那个元素,因此高度为7的指针无论怎么向内移动,水高度都不会超过3,而这个过程中宽度又是单调递减的,因此right指针向内移动,所有的结果都小于当前的水量。

比如这个情况:

在这里插入图片描述

虽然right向内移动,找到了比7更大的元素,但是由于此时水高度取决于3,而且宽度还变小了,最后总水量没有变大。

因此每次都把比元素值较小的那个指针向内移动

代码如下:

class Solution
{
public:int maxArea(vector<int>& height){int left = 0;int right = height.size() - 1;int ret = -1;while (left <= right){int w = right - left;//宽度int h = min(height[left], height[right]);//高度ret = max(ret, w * h);//更新最大水量//每次都让较小的元素向内枚举if (height[left] > height[right])right--;elseleft++;}return ret;}
};

总结

双指针

  • 数组划分使用双指针算法。

一般处理为[A区域][B区域]...[待处理]这样的格式,当新元素符合哪一个区域特性,就放到哪一个区域中。

快慢指针

  • 循环问题,利用快慢指针来判断是否有循环。

相遇就是有环,如果fast走到结尾就是无环。

如果要找循环开始节点,一个指针从头开始走,一个指针从相遇点开始走,最后会在环入口相遇。

对撞指针

  • 在一个有序区间中查找两个元素,计算得到固定值的题型,使用对撞指针。

  • 如果利用对撞指针下标向内枚举,对组成结果的影响是单调的,就可以考虑对撞指针。

对撞指针的特点在于利用单调性减小搜索范围。


相关文章:

算法:双指针

算法&#xff1a;双指针 双指针快慢指针对撞指针总结 双指针 LeetCode 283.移动零 以上题目要求我们把所有0移动到数组的末尾&#xff0c;也就是说&#xff0c;我们要把数组转化为以下状态&#xff1a; [ 非0区域 ] [ 0区域 ] 像这种把一个数组划分为多个区域的题型&#xff0…...

MySQL一些特殊功能的索引(6/16)

特殊功能性索引 B-Tree索引&#xff1a; InnoDB的默认索引类型&#xff0c;适用于多种查询操作。 可以用于等值查询、范围查询和索引列的组合查询。 创建B-Tree索引的示例&#xff1a; CREATE INDEX index_name ON table_name (column1, column2);全文索引&#xff08;FULLTEX…...

ES11-12

1-ES11-Promise.allSettled Promise.allSettled0)方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。 简单来说不管成功失败都会调用.then()&#xff0c;然后处理成功和失败的结果 const promises [ …...

【学习笔记】Vue3源码解析:第三部分-获取computed的值;实现computed

课程地址&#xff1a;【已完结】全网最详细Vue3源码解析&#xff01;&#xff08;一行行带你手写Vue3源码&#xff09; 第三部分-获取computed的值&#xff1b;实现computed&#xff1a;&#xff08;对应课程的第18-21节&#xff09; 第22节&#xff1a;《获取computed的值》 …...

顺序表(C语言版)

前言&#xff1a;本篇文章我们来详细的讲解一下顺序的有关知识&#xff0c;这篇文章中博主会以C语言的方式实现顺序表。以及用顺序表去实现通讯录的代码操作。 目录 一.顺序表的概念 二.顺序表的分类 1.静态顺序表 三.动态顺序表的实现 1.顺序表的初始化 2.顺序表的尾插…...

Python高质量函数编写指南

The Ultimate Guide to Writing Functions 1.视频 https://www.youtube.com/watch?vyatgY4NpZXE 2.代码 https://github.com/ArjanCodes/2022-funcguide Python高质量函数编写指南 1. 一次做好一件事 from dataclasses import dataclass from datetime import datetimedatacl…...

探索Spring、Spring Boot和Spring Cloud的奇妙关系(二)

本系列文章简介&#xff1a; 在当今快节奏、高竞争的软件开发世界中&#xff0c;构建可靠、高效的应用程序是至关重要的。而Spring框架一直以来都是业界领先的Java开发框架之一&#xff0c;帮助开发者简化了复杂的任务&#xff0c;并提供了丰富的功能和强大的支持。 然而&#…...

Mysql的事务隔离级别以及事务的四大特性。

MySQL 的事务隔离级别是数据库管理系统中的一个重要概念&#xff0c;它决定了事务如何隔离和影响其他并发事务。MySQL 支持四种事务隔离级别&#xff0c;分别是&#xff1a;读未提交&#xff08;READ UNCOMMITTED&#xff09;、读已提交&#xff08;READ COMMITTED&#xff09;…...

人工智能_大模型023_AssistantsAPI_01_OpenAI助手的创建_API的调用_生命周期管理_对话服务创建---人工智能工作笔记0159

先来说一下一些问题: 尽量不要微调,很麻烦,而且效果需要自己不断的去测试. 如果文档中有图表,大量的图片去分析就不合适了. 是否用RAG搜索,这个可以这样来弄,首先去es库去搜能直接找到答案可以就不用去RAG检索了,也可以设置一个分,如果低于60分,那么就可以去进行RAG检索 微…...

锁策略总结

锁策略 悲观锁和乐观锁 乐观锁和悲观锁不是具体类型的锁而是指两种不同的对待加锁的态度&#xff0c;这两个锁面对锁冲突的态度是相反的。 乐观锁&#xff1a;认为不存在很多的并发操作&#xff0c;因此不需要加锁。悲观锁&#xff1a;认为存在很多并发操作&#xff0c;因此需…...

蓝桥杯备考day2

1.1 map及其函数 map 提供一对一的数据处理能力&#xff0c;由于这个特性&#xff0c;它完成有可 能在我们处理一对一数据的时候&#xff0c;在编程上提供快速通道。map 中的第一 个值称为关键字(key)&#xff0c;每个关键字只能在 map 中出现一次&#xff0c;第二个称为该 关…...

Mac电脑安装蚁剑

1&#xff1a; github 下载源码和加载器&#xff1a;https://github.com/AntSwordProjectAntSwordProject GitHubAntSwordProject has 12 repositories available. Follow their code on GitHub.https://github.com/AntSwordProject 以该图为主页面&#xff1a;antSword为源码…...

品牌百度百科词条创建多少钱?

百度百科作为国内最具权威和影响力的知识型平台&#xff0c;吸引了无数品牌和企业争相入驻。一个品牌的百度百科词条&#xff0c;不仅是对品牌形象的一种提升&#xff0c;更是增加品牌曝光度、提高品牌知名度的重要途径。品牌百度百科词条创建多少钱&#xff0c;这成为了许多企…...

Linux安装及管理程序

目录 一.Linux应用程序基础 1.应用程序与系统命令的关系 2.典型应用程序的目录结构 3.常见的Linux软件包封装类型 二.RPM 软件包管理工具 1.RPM 软件包管理器 Red-Hat Package Manger 2.RPM软件包 3.RPM命令 三.源代码编译安装 1. yum 软件包管理器&#xff1a; 配…...

Mybatis generate xml 没有被覆盖

添加插件即可 <plugin type"org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>...

MercadoLibre(美客多)入仓预约系统操作流程-自动化约号(开篇)

目录 一、添加货件信息 二、输入货件信息 三、选择发货 四、填写交货日期 五、注意事项 MercadoLibre&#xff08;美客多&#xff09;于2021年10月18号上线了新预约入仓系统&#xff0c;在MercadoLibre美客多平台上&#xff0c;新入仓预约系统是一项非常重要的功能&#x…...

Unity TextMeshProUGUI 获取文本尺寸·大小

一般使用ContentSizeFitter组件自动变更大小 API 渲染前 Vector2 GetPreferredValues(string text)Vector2 GetPreferredValues(string text, float width, float height)Vector2 GetPreferredValues(float width, float height) 渲染后 Vector2 GetRenderedValues()Vector…...

Sonar下启动发生错误,elasticsearch启动错误

Download | SonarQube | Sonar (sonarsource.com) 1.首先我的sonar版本为 10.4.1 &#xff0c;java版本为17 2.sonar启动需要数据库,我先安装了mysql, 但是目前sonar从7.9开始不支持mysql&#xff0c;且java版本要最少11,推荐使用java17 3.安装postsql,创建sonar数据库 4.启…...

Git常用命令以及异常信息汇总

常用命令&#xff1a; 查看本地分支&#xff1a; git branch 创建一个新仓库 git clone 仓库地址xxxxx cd 目标目录 git switch -c main touch README.md git add README.md git commit -m "add README" git push -u origin main 推送现有文件夹 cd 目标目录 git in…...

解释Python中的RESTful API设计和实现

解释Python中的RESTful API设计和实现 RESTful API&#xff0c;即符合REST&#xff08;Representational State Transfer&#xff0c;表述性状态转移&#xff09;架构风格的Web服务接口&#xff0c;已成为现代Web应用程序通信的标准。Python作为一种灵活且强大的编程语言&…...

Qwen3-32B-Chat入门指南:WebUI中Stream输出、Stop Token、Temperature调节说明

Qwen3-32B-Chat入门指南&#xff1a;WebUI中Stream输出、Stop Token、Temperature调节说明 1. 镜像概述与环境准备 1.1 镜像基本信息 本镜像为Qwen3-32B-Chat模型的私有部署优化版本&#xff0c;专为RTX 4090D 24GB显存显卡设计&#xff0c;主要特点包括&#xff1a; 硬件适…...

AI入门指南:盘点那些媲美ChatGPT的国产大模型工具

1. 国产AI大模型崛起&#xff1a;为什么你需要关注它们&#xff1f; 最近两年&#xff0c;AI大模型的发展速度让人瞠目结舌。作为AI领域的从业者&#xff0c;我亲眼见证了国产大模型从追赶到并驾齐驱的整个过程。很多人可能不知道&#xff0c;现在国内已经有好几款大模型在实际…...

CentOS 7.6下NetBackup 9.1安装全攻略:从账号配置到许可证激活

CentOS 7.6企业级备份方案&#xff1a;NetBackup 9.1深度部署指南 在企业IT基础设施中&#xff0c;数据备份是确保业务连续性的最后防线。作为业界领先的企业级备份解决方案&#xff0c;Veritas NetBackup以其卓越的可靠性、广泛的平台兼容性和丰富的功能集&#xff0c;成为众多…...

当GAN遇上行人重识别:用StyleGAN2生成数据提升ReID模型效果

当GAN遇上行人重识别&#xff1a;用StyleGAN2生成数据提升ReID模型效果 行人重识别&#xff08;ReID&#xff09;技术作为智能安防领域的核心组件&#xff0c;其性能瓶颈往往受限于真实场景数据的稀缺性。传统数据增强方法在应对跨摄像头视角变化、光照差异等复杂场景时显得力不…...

天地图JavaScript API实战:多边形面积计算与交互式绘制

1. 天地图JavaScript API基础入门 第一次接触天地图JavaScript API的开发者可能会觉得有点懵&#xff0c;其实它和我们常用的百度地图、高德地图API类似&#xff0c;都是用来在网页上展示地图和实现地理信息功能的工具链。我刚开始用的时候也踩过不少坑&#xff0c;后来发现只要…...

SpringBoot+Mybatis-plus多数据源实战:跨库操作避坑指南

SpringBootMybatis-plus多数据源实战&#xff1a;跨库操作避坑指南 在微服务架构盛行的今天&#xff0c;单一数据源已无法满足复杂业务场景的需求。许多企业级应用需要同时对接多个数据库系统&#xff0c;可能是为了读写分离、分库分表&#xff0c;或是需要整合不同业务系统的数…...

洞察大数据领域GDPR的最新动态

洞察大数据领域GDPR的最新动态&#xff1a;从合规红线到数据价值的平衡艺术关键词&#xff1a;GDPR、数据隐私、大数据合规、被遗忘权、跨境数据传输、隐私增强技术、AI伦理摘要&#xff1a;在大数据浪潮中&#xff0c;个人数据已成为“数字石油”&#xff0c;但欧盟《通用数据…...

Flutter多版本管理神器FVM保姆级教程:从安装到避坑全攻略

Flutter多版本管理神器FVM保姆级教程&#xff1a;从安装到避坑全攻略 Flutter开发者在面对不同项目需要切换SDK版本时&#xff0c;常常陷入环境配置的泥潭。FVM&#xff08;Flutter Version Management&#xff09;作为专为Flutter设计的版本管理工具&#xff0c;能像时间机器般…...

伪代码示意:海岸线几何参数

comsol海水入侵海岸 当海水悄悄爬上岸&#xff1a;用COMSOL模拟海岸带盐水入侵 海岸带的地下水系统像一块海绵&#xff0c;淡水与海水在这里暗中较劲。气候变化和过度开采地下水让海水入侵成了沿海地区的噩梦。今天咱们用COMSOL整点硬核操作&#xff0c;看看盐水是如何“偷渡”…...

飞书多维表格API实战:用Dify实现智能票据分类归档系统

飞书多维表格与Dify深度整合&#xff1a;打造企业级智能票据管理中枢 在数字化转型浪潮中&#xff0c;企业财务流程的智能化升级已成为不可逆转的趋势。传统票据处理方式——人工分类、手动录入、Excel归档——不仅效率低下&#xff0c;还容易因疲劳导致数据错误。根据行业调研…...