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

【算法】双指针(上)

目录

双指针

左右指针(对撞指针)

快慢指针

移动零

双指针解题

复写零

暴力解题

双指针解题(快慢指针)

快乐数

双指针解题(快慢指针)

盛最多水的容器

暴力解题(会超时)

双指针解题(左右指针)

有效三角形的个数

暴力解题

双指针解题(左右指针)


双指针

常见的双指针有两种形式,一种是左右指针(对撞指针),一种是快慢指针

左右指针(对撞指针)

·左右指针从顺序结构的两端向中间移动。一个指针从最左端开始,另一个从最右端开始,然后逐渐往中间逼近

·左右指针的终止条件无非就只有两种情况(也可能在循环内部找到结果直接跳出循环)

·left==right(两个指针指向同一个位置)

·left>right(两个指针错开)

快慢指针

又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上移动

这种方法对于处理环形链表或数组非常有用

其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想

快慢指针的实现方式有很多种,最常用的一种就是:

·在一次循环中,每次让慢的指针向后移动一位,而快的指针往后移动两位,实现一快一慢

【数组分两块】是非常常见的一种提醒,主要就是根据一种划分方式,将数组的内容分成左右两部分。这种类型的题,一般就是使用双指针来解决

移动零

题目链接:283. 移动零 - 力扣(LeetCode)

题目描述:

给定⼀个数组 nums ,编写⼀个函数将所有 0 移动到数组的末尾,同时保持⾮零元素的相对顺

序。

请注意 ,必须在不复制数组的情况下原地对数组进⾏操作。

⽰例 1:

输⼊: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]

⽰例 2:

输⼊: nums = [0]

输出: [0]

双指针解题

解题思路(快排的思想:数组划分区间--数组分成两块):

使用双指针。用一个cur指针来遍历整个数组,另一个dest指针用来记录非零数序列的最后一个位置。然后根据cur指针遍历到的数进行分类处理。

大致流程为:

1.初始化cur=0,dest=-1。

注意:我们这里初始化dest=-1。这里不将dest设置为0的原因是:如若将dest设置为0,dest的指向便不再是非零数序列的最后一个位置了。(因为下标为0的话,也占一个元素啊)

2.令cur遍历数组,遍历到的元素有两种情况:

·遇到的元素不是0,dest++。并交换cur和dest位置处的元素,之后让cur++。

这里dest++有两个含义:首先是因为cur指针找到一个非0数,所以dest后移一位,表示非0数的序列+1。其次是因为dest++之后,指向的元素就是0元素(因为非0元素区间末尾的后一个元素就是0)。

·遇到的元素是0,cur直接++。

解题代码

class Solution {public void moveZeroes(int[] nums) {for(int cur=0,dest=-1;cur<nums.length;cur++){if(nums[cur]!=0){dest++;//交换cur和dest位置处的元素int temp=nums[cur];nums[cur]=nums[dest];nums[dest]=temp;}}}
}

我们上述代码是初始化dest= -1。让dest指向非0序列的最后一个位置。

现在我们初始化dest=0。看看代码有哪里不同

class Solution {public void moveZeroes(int[] nums) {for(int cur=0,dest=0;cur<nums.length;cur++){if(nums[cur]!=0){int temp=nums[cur];nums[cur]=nums[dest];nums[dest]=temp;dest++;}}}
}

我们发现,表面来看,不过是dest++ 一个放前面和一个后面。但我们要清楚里面的门道。将dest初始为0的,则令dest指向非0序列末尾的后一个元素。

复写零

题目链接:1089. 复写零 - 力扣(LeetCode)

题目描述:

给你⼀个⻓度固定的整数数组 arr ,请你将该数组中出现的每个零都复写⼀遍,并将其余的元素

向右平移。

注意:请不要在超过该数组⻓度的位置写⼊元素。请对输⼊的数组就地进⾏上述修改,不要从函数返

回任何东西。

⽰例 1:

输⼊: arr = [1,0,2,3,0,4,5,0]

输出: [1,0,0,2,3,0,0,4]

解释:

调⽤函数后,输⼊的数组将被修改为: [1,0,0,2,3,0,0,4]

暴力解题

思路:让指针L1遍历数组,一旦遇到元素0,便从此处开始,一直到数组末尾,每个元素后移一位。由于元素后移一位,实现复写0,所以指针L1需要格外进行一次++,跳过复写的0,不然会导致后续元素都为0.

注意:如果我们只用一个指针L1无法【从前向后】实现所有元素后移一位。因为,如果【从前向后】实现元素后移的话,会把未移动的元素给覆盖掉。所以我们这里【从后向前】实现元素后移

解题代码

class Solution {public void duplicateZeros(int[] arr) {int l1=0;int length=arr.length;for(;l1<length;l1++){if(arr[l1]==0){for(int j=length-1;j>l1;j--){arr[j]=arr[j-1];}l1++;}}}
}

双指针解题(快慢指针)

解题思路

由于复写0会使元素+1,然而数组长度不变,数组便从末尾开始舍弃元素。所以我们只需找到 新复写数组的最后一个元素(即旧数组中最后一个复写的数)。然后进行复写

核心步骤

·先找到最后一个复写的数

·然后【从后向前】进行复写

注意:由于【从前向后】进行原地复写操作,会导致没有复写的数【被覆盖掉】。所以这里选择【从后往前】进行复写

大致流程为

a.初始化两个指针cur=0,dest=-1

b.找到最后一个复写的数

·当cur<数组长度,执行下面循环

1.若cur位置处的元素为0,dest后移两位,否则后移一位。注意:这里的dest指针可以看作记录元素个数(每移动一步相等于记录一个元素)。(保证移动步数=元素个数即可,但当最后一个复写的数为0时,移动步数会多1步,dest指针会越界)

2.判断dest指针此时是否已经到结束位置(数组末尾亦或者是越界),如果到了便终止循环

3.如果没有结束,cur++,继续循环判断

c.判断dest是否越界(最后一个复写的数是否为0),如果越界,便执行下面三步:

  1. 将数组最后一个元素的值修改成0
  2. cur指针向前移动一步(跳过最后一个复写的数(0)
  3. dest指针向前移动两步(指向倒数第二个数--跳过数组最后一个元素)

注意:我们要知道,数组最后一个元素和最后一个复写的数,这两个名词并不等同

d.从cur位置开始往前遍历原数组,还原出复写后的数组

解题代码

class Solution {public void duplicateZeros(int[] arr) {int cur=0;int dest=-1;int n=arr.length;//找到最后一个复写的数while(cur<n){if(arr[cur]!=0){dest++;}else{dest+=2;}if(dest>=n-1)break;//结束条件cur++;}//处理越界情况--即最后一个复写的数为0if(dest==n){arr[n-1]=0;cur--;dest-=2;}//从后往前还原出复写后的数组for(;cur>=0;cur--){if(arr[cur]!=0){arr[dest--]=arr[cur];}else{arr[dest--]=0;arr[dest--]=0;}}}
}

快乐数

题目链接:202. 快乐数 - 力扣(LeetCode)

题目描述:

编写⼀个算法来判断⼀个数 n 是不是快乐数。

「快乐数」 定义为:

对于⼀个正整数,每⼀次将该数替换为它每个位置上的数字的平⽅和。

然后重复这个过程直到这个数变为 1,也可能是⽆限循环但始终变不到 1

如果这个过程 结果为 1 ,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false

⽰例 1:

输⼊: n = 19

输出: true

解释:

19 -> 1 * 1 + 9 * 9 = 82

82 -> 8 * 8 + 2 * 2 = 68

68 -> 6 * 6 + 8 * 8 = 100

100 -> 1 * 1 + 0 * 0 + 0 * 0 = 1

⽰例 2:

输⼊: n = 2

输出: false

解释:(这⾥省去计算过程,只列出转换后的数)

2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16

往后就不必再计算了,因为出现了重复的数字,最后结果肯定不会是 1

题目解析

我们将 【对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和】这一操作用 function方法来解决。

重点是:题目定义中的【无限循环】。

意思是:

1.如果这个数n不是快乐数,就会【无限循环】但始终变不到1。

2.然而,如果这个数是快乐数,即最终会变到1,此时1便会【无限循环】。

所以,无论这个数n是不是快乐数,都会【无限循环】

所以,当我们不断循环function方法,计算一定会【无限循环】,【无限循环】的方式有两种:

情况1:在旧的数据中【无限循环】,但始终变不到1。

情况2:一直在1中进行【无限循环】

【无限循环】原理解释:

由于int最大值2^31-1=2147483647,哪怕是9999999999这样大的数据,各个位置上的数字的平方和为810。所以在int范围内的数n,其各个位置上的数字的平方和一定在[1,810]区间内。极限情况下,一个数变化811次之后,必然会形成一个循环。因此使用【快慢指针】来解决本题

双指针解题(快慢指针)

解题思路

当我们重复使用function方法时,数据会陷入【无限循环】中。

【快慢指针】的一个特性就是,在一个圆圈中,快指针总是会追上慢指针的。也就是说,它们总会相遇在一个位置上。如果这个位置是1,那么这个数一定是快乐数;否则,这个数便不是快乐数

重点:相遇位置以及该数是不是1

大致流程为:

  1. 写一个function方法:用来求数n每个位置上的数字的平方和
  2. 让slow每次走一步,fast每次走两步,判断相遇位置处的元素是否为1。如果是1,输出true;否则,输出false

题目代码

class Solution {public static boolean isHappy(int n) {int slow=nint fast=function(n);//注意,这里初始化fast!=slow是因为,我们要求它俩相遇的位置//当fast指针追上slow指针,并且都为1时,返回truewhile(slow!=fast){slow=function(slow);//走一步fast=function(function(fast));//走两步}return slow==1;}private static int function(int n) {int sum=0;while(n!=0){int g=n%10;sum+=g*g;n/=10;}return sum;}
}

盛最多水的容器

题目链接:11. 盛最多水的容器 - 力扣(LeetCode)

题目描述:

给定⼀个⻓度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) (i,

height[i])

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的⽔。

返回容器可以储存的最⼤⽔量。

说明:你不能倾斜容器。

⽰例 1:

输⼊: [1,8,6,2,5,4,8,3,7]

输出: 49

解释:图中垂直线代表输⼊数组 [1,8,6,2,5,4,8,3,7] 。在此情况下,容器能够容纳⽔(表⽰为蓝⾊部分)的最⼤值为 49

暴力解题(会超时)

思路:一个一个进行遍历,找出其中容积(V)最大的值

容积公式=长*宽

设两指针i,j,初始化i=0,j=i+1,我们知道两指针之间的距离=宽度=j-i。由于容器的高度由两板中的短板决定,所以容积公式为:v=(j-i)*min(height[i],height[j])

解题代码

class Solution {public int maxArea(int[] height) {int n=height.length;int v=0;//v=(j-i)*min(height[i],height[j])int sum=0;for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){v=(j-i)*Math.min(height[i],height[j]);if(v>=sum){sum=v;}}}return sum;}
}

双指针解题(左右指针)

解题思路

设两个指针left,right分别指向容器的左右两个端点。

此时容器的容积v=(right-left)*min(height[left],height[right])

容器的【左边界】为height[left],【右边界】为height[right]

我们先假设【左边界】小于【右边界】

如果我们固定一个边界,改变另一个边界,容积v会有以下变化形式:

   1.容器的宽度一定变小

   2.由于【左边界】小,所以决定了容器的高度。如果改变【左边界】,容器的高度便不确定(相较于原先的【左边界】),但是一定不会超过【右边界】的高度,因此容器的容积v可能会增大

   3.如果改变右边界,无论【右边界】移动到哪里,新容器的高度一定不会超过【左边界】,也就是容器的高小于等于【左边界】,但是容器的宽度随着【右边界】的移动而减少,因此容器的容积v一定会变小

我们这里可以把【左边界】替换为较小值,【右边界】替换为较大值。

根据上述假设,移动【右边界】会导致容积v变小,所以,我们这里只移动【较小值】,并比较容积v,便能得到最大值

解题代码

class Solution {public static int maxArea(int[] height) {int left=0;int right=height.length-1;int v=0;int max=0;while(left<right){v=(right-left)*Math.min(height[left],height[right]);if(v>=max){max=v;}if(height[left]<height[right]) {left++;}else{right--;}}return max;}
}

有效三角形的个数

题目链接:611. 有效三角形的个数 - 力扣(LeetCode)

题目描述:

给定⼀个包含⾮负整数的数组 nums ,返回其中可以组成三⻆形三条边的三元组个数。

⽰例 1:

输⼊: nums = [2,2,3,4]

输出: 3

解释:有效的组合是:

2,3,4 (使⽤第⼀个 2)

2,3,4 (使⽤第⼆个 2)

2,2,3

⽰例 2:

输⼊: nums = [4,2,3,4]

输出: 4

解释:

4,2,3

4,2,4

4,3,4

2,3,4

暴力解题

解题思路:三层for循环枚举出所有的三元组

构成三角形的条件:需要满足任意两边之和大于第三边。但是实际上只需让较小的两条边之和大于第三边即可。因此我们这里先排序,再枚举。

解题代码

lass Solution {public static int triangleNumber(int[] nums) {Arrays.sort(nums);int n=nums.length;int count=0;for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){for(int t=j+1;t<n;t++){if(nums[i]+nums[j]>nums[t]){count++;}}}}return count;}
}

双指针解题(左右指针)

由于我们左右指针只能表示两个元素,但为了找出这个三元组,可以尝试固定一条边,这样只需要找到一个二元组即可。

解题思路

1.先将数组排序

2.我们这里选择固定一个【最长边】,然后在比【最长边】小的有序数组中找出一个二元组,使这个二元组之和大于这个【最长边】。由于数组是有序的,我们这里采用【左右指针】。

  假设最长边在下标i处,区间[left,right]是i位置左边的区间--也就是比i小的区间:

  如果nums[left]+nums[right]>nums[i]:

   ·说明[left,right-1](因为left处的元素是最小的)区间上的所有元素都可以和nums[right]构成一个二元组,使其之和大于nums[i]

   ·满足条件的有(right-1-left)+1=right-left种

   ·此时right处的元素的所有情况相当于全部考虑完毕,right--,进入下一轮判断

 如果nums[left]+nums[right]<nums[i]:

   ·说明left处的元素是不能和[left+1,right](因为right处的元素已经是最大的了)区间上的元素构成一个二元组,使其之和大于nums[i]

   ·left处的元素舍去,left++

解题代码

class Solution {public static int triangleNumber(int[] nums) {Arrays.sort(nums);int n=nums.length;int count=0;//左右指针:固定一个最长边(i)---下标[2,n-1]for(int i=n-1;i>=2;i--){int left=0;int right=i-1;while(left<right){if(nums[left]+nums[right]>nums[i]){//[left,right-1]区间上的元素 和nums[right]的和都大于nums[i]count+=right-left;//注意:这里不用count++,因为right--;//选择较小的数 判断是否大于固定的最长边}else{left++;}}}return count;}
}

相关文章:

【算法】双指针(上)

目录 双指针 左右指针(对撞指针) 快慢指针 移动零 双指针解题 复写零 暴力解题 双指针解题(快慢指针) 快乐数 双指针解题(快慢指针) 盛最多水的容器 暴力解题(会超时) 双指针解题(左右指针) 有效三角形的个数 暴力解题 双指针解题(左右指针) 双指针 常见的双指…...

【Linux Redis】关于用docker拉取Redis后,让虚拟机运行起来redis,并使得其可以连接到虚拟机外的navicat。

步骤一&#xff1a;拉取Redis镜像 docker pull redis 这个命令会下载最新版本的Redis镜像到你的本地Docker仓库中。你也可以指定一个具体的版本号&#xff0c;例如docker pull redis:6.2.6&#xff0c;来拉取特定版本的Redis镜像。 如果拉取遇到问题请参考【Linux AnolisOS】关…...

用deepseek学大模型04-模型可视化与数据可视化

deepseek.com: pytorch可视化工具 生成神经网络图 在 PyTorch 中&#xff0c;可视化神经网络结构的常用工具和方法有以下几种&#xff0c;以下将详细介绍它们的用法&#xff1a; 1. TensorBoard (PyTorch 官方集成) PyTorch 通过 torch.utils.tensorboard 支持 TensorBoard&a…...

一周学会Flask3 Python Web开发-post请求与参数获取

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili app.route 装饰器默认只支持get请求。假如我们要让绑定的视图函数支持其他请求方式&#xff0c;我们可以在methods属性里配置…...

第3章 .NETCore核心基础组件:3.1 .NET Core依赖注入

3.1.1 什么是控制反转、依赖注入 杨老师在书中进行了一系列的文字阐述&#xff0c;总结一下就是&#xff1a;软件设计模式中有一种叫做【控制反转】的设计模式&#xff0c;而依赖注入是实现这种设计模式的一个很重要的方式。也就是说学习依赖注入&#xff0c;是学习怎样实现控…...

cs*n 网页内容转为html 加入 onenote

csdn上有好用的内容&#xff0c;我们怎么将它们加到 onenote 里吃灰呢。 一、创建 新html create_html.py import sysdef create_html_file(filename):# 检查是否提供了文件名if not filename:print("请提供HTML文件名")return# 创建HTML内容html_content f"…...

平板作为电脑拓展屏

有线串流&#xff08;速度更快&#xff09; spacedesk 打开usb对安卓的连接 用usb线直接连接电脑和平板 无线串流&#xff08;延迟高&#xff0c;不推荐&#xff09; todesk pc和手机端同时下载软件&#xff0c;连接后可以进行远程控制或扩展屏幕 spacedesk 连接到同一个…...

Pytorch实现论文之一种基于扰动卷积层和梯度归一化的生成对抗网络

简介 简介:提出了一种针对鉴别器的梯度惩罚方法和在鉴别器中采用扰动卷积,拟解决锐梯度空间引起的训练不稳定性问题和判别器的记忆问题。 论文题目:A Perturbed Convolutional Layer and Gradient Normalization based Generative Adversarial Network(一种基于扰动卷积层…...

关系数据库标准语言SQL

1.SOL称为结构化查询语言&#xff0c;它是由1974年由Boyce和Chamberlin提出的&#xff0c;1975年至1979年IBM公司的San Jose Research Laboratory研制了关系数据库管理系统的原型系统SystemR,并实现了这种语言。 2.SQL(Structured Ouery Language)称为结构化查询语言 3.SQL数…...

AI工具篇:利用DeepSeek+Kimi 辅助生成综述汇报PPT

随着科研和学术报告需求的增加&#xff0c;如何高效地准备一份结构清晰、内容充实的PPT已成为许多研究者的挑战。 传统的PPT制作过程繁琐&#xff0c;需要大量文献收集、数据分析和设计工作&#xff0c;而AI工具能够帮助提升效率&#xff0c;减少重复劳动。 本文将介绍如何使用…...

学习总结2.18

在原本基本的数船的基础上&#xff0c;增加了船不能畸形的要求&#xff0c;船只能是矩形&#xff0c;由此需要在dfs找船前确定是否有畸形船 .* ** *. ** ** .* ** *. 出现畸形船的情况如上图&#xff0c;即两艘船有一个交集时&#xff0c;此时就可以判断出bad pl…...

electron下载文件,弹窗选择下载路径,并通知下载进度

1&#xff1a;在window.js中 引入session import { app, BrowserWindow, ipcMain, dialog, shell, session } from electron; 2&#xff1a;发送下载请求 // 在主进程监听渲染进程发送的 start-download 事件ipcMain.on(start-download, async (event, downloadUrl) > {l…...

【Docker】容器被停止/删除的方式及命令:全面解析与实践指南

文章目录 引言一、容器的生命周期二、停止容器的命令及方式1. docker stop 命令2. docker kill 命令3. docker pause 和 docker unpause 命令4. docker restart 命令 三、删除容器的命令及方式1. docker rm 命令2. docker container prune 命令3. docker rm 与 docker rmi 的区…...

线上就医全流程医药机构接入文档接口代码-医保就医接口php-demo版本

2025年2月18日11:28:03 国密算法开发库推荐 lpilp/guomi 我测试过php 7.2 - 8.0都可以兼容&#xff0c;如果有能力可以自己开发 目前已经开发了核心的接口的测试demo,并且封装了工具类直接写业务逻辑即可&#xff0c;并且已经有线上项目在使用&#xff0c;如果需要demo代码可…...

缓存三大问题及其解决方案

缓存三大问题及其解决方案 1. 前言 ​ 在现代系统架构中&#xff0c;缓存与数据库的结合使用是一种经典的设计模式。为了确保缓存中的数据与数据库中的数据保持一致&#xff0c;通常会给缓存数据设置一个过期时间。当系统接收到用户请求时&#xff0c;首先会访问缓存。如果缓…...

大语言模型常用微调与基于SFT微调DeepSeek R1指南

概述 大型语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;的微调&#xff08;Fine-tuning&#xff09;是指在一个预训练模型的基础上&#xff0c;使用特定领域或任务的数据对模型进行进一步训练&#xff0c;以使其在该领域或任务上表现更好。微调是迁移…...

LabVIEW的吞雨测控系统

本案例介绍了一种基于LabVIEW开发的吞雨测控系统&#xff0c;该系统通过建模仿真分析不同控制器模式下的阶跃信号响应&#xff0c;从而选择了最适合的控制器。为了有效解决在控制流量过程中出现的振荡收敛和流量信号大扰动问题&#xff0c;系统采用了改进的积分分离PID算法&…...

redis基础命令

基于内存的数据存储系统 redis中数据以键值对存储的 键区分大小写 redis默认都是使用字符串存储数据 //启动服务 redis-server //连接客户端 redis-cli //连接客户端&#xff0c;--raw表示以原始的形式显示内容 redis-cli --rawset keyname valueget keynamedel keyname //…...

基于Java+SpringBoot+Vue的前后端分离的校园闲置物品交易网站

基于JavaSpringBootVue的前后端分离的校园闲置物品交易网站 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接…...

K8s 证书认知(K8s Certificate Awareness)

K8s 证书认知 在谈起 Kubernetes 证书时&#xff0c;总感觉其涵盖的内容繁多&#xff0c;仿佛千头万绪&#xff0c;让人不知该从何处着手阐述。为了更好地理清思路&#xff0c;本文将对相关内容进行系统的梳理和记录。 1、证书及链路关系 Kubeadm部署的集群&#xff0c;K8s …...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...

【实施指南】Android客户端HTTPS双向认证实施指南

&#x1f510; 一、所需准备材料 证书文件&#xff08;6类核心文件&#xff09; 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...

【Java】Ajax 技术详解

文章目录 1. Filter 过滤器1.1 Filter 概述1.2 Filter 快速入门开发步骤:1.3 Filter 执行流程1.4 Filter 拦截路径配置1.5 过滤器链2. Listener 监听器2.1 Listener 概述2.2 ServletContextListener3. Ajax 技术3.1 Ajax 概述3.2 Ajax 快速入门服务端实现:客户端实现:4. Axi…...

Python爬虫(四):PyQuery 框架

PyQuery 框架详解与对比 BeautifulSoup 第一部分&#xff1a;PyQuery 框架介绍 1. PyQuery 是什么&#xff1f; PyQuery 是一个 Python 的 HTML/XML 解析库&#xff0c;它采用了 jQuery 的语法风格&#xff0c;让开发者能够用类似前端 jQuery 的方式处理文档解析。它的核心特…...